home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 422_04 / basic.asm < prev    next >
Assembly Source File  |  1994-02-14  |  65KB  |  1,976 lines

  1.     TITLE    MICRO BASIC
  2. **************************************************************
  3. *                       MICRO-BASIC                          *
  4. *------------------------------------------------------------*
  5. *   A SMALL INTEGER BASIC INTERPRETER FOR THE 8080/8085/Z80  *
  6. *                                D.F. DUNFIELD  JAN 25/1983  *
  7. *------------------------------------------------------------*
  8. *                      BASIC COMMANDS                        *
  9. *                                                            *
  10. *  CLEAR,    DATA,     DIM,      END,      EXIT,     FOR,    *
  11. *  GOSUB,    GOSUB(N), GOTO,     GOTO(N),  IF/THEN,  INPUT,  *
  12. *  LET,      LIF/THEN, LIST,     LOAD,     NEW,      NEXT,   *
  13. *  ORDER,    PLOT,     PRINT,    READ,     REM,      RETURN, *
  14. *  RUN,      SAVE,     SIZE,     STOP,     USR,      <EDIT>  *
  15. *------------------------------------------------------------*
  16. *                     BASIC OPERATORS                        *
  17. *                                                            *
  18. * NUMERIC:     + - * % / \ & | ; ( ) < = > == -= <= >=       *
  19. * CHARACTER:   + = == -=                                     *
  20. * OTHER:       : # $ @ ? [ ] ( )                             *
  21. *------------------------------------------------------------*
  22. *                      BASIC VARIABLES                       *
  23. *                                                            *
  24. *     A - Z ......... 16 BIT SIMPLE INTEGER VARIABLES.       *
  25. *     A$ - Z$ ....... SIMPLE CHARACTER VARIABLES. < 36 CHARS *
  26. *     A[N] - Z[N] ... 16 BIT INTEGER ARRAYS.                 *
  27. *     @[N] .......... PSEUDO MEMORY REFERENCE ARRAY.         *
  28. *     @[N]$ ......... NUMERIC TO CHARACTER CONVERSION.(CHR$) *
  29. *     ? ............. PSEUDO RANDOM NUMBER GENERATOR.        *
  30. *------------------------------------------------------------*
  31. *                        MEMORY MAP                          *
  32. *                                                            *
  33. *    0000-03FF     1K SYSTEM MONITOR (IN ROM).               *
  34. *    0400-0FFF     3K BASIC INTERPRETER (IN ROM).            *
  35. *    1000-13FF     1K MEMORY MAPPED 64*16 VIDEO DISPLAY      *
  36. *    1400-15FF     0.5K POINTERS, STACKS, BUFFERS.           *
  37. *    1600-19FF     1K VARIABLES AND POINTERS.                *
  38. *    1A00-FFFF     PROGRAM AND ARRAY STORAGE.                *
  39. **************************************************************
  40.     PAGE
  41. *
  42. **************************************************************
  43. *                   CONSTANTS AND EQUATES
  44. **************************************************************
  45. *
  46. * MONITOR ROUTINES
  47. *
  48. IN    EQU    $23F        INPUT ROUTINE ADDRESS
  49. OUT    EQU    $162        OUTPUT ROUTINE ADDRESS
  50. CTRLC    EQU    $27E        CONTROL-C TEST ROUTINE ADDRESS
  51. EXIT    EQU    $37        TERMINATION RETURN ADDRESS
  52. GETR    EQU    $2EB        ROUTINE TO LOAD INTEL HEX FORMAT
  53. TDUMP    EQU    $D6        ROUTINE TO DUMP IN INTEL HEX FORMAT
  54. TON    EQU    $396        ROUTINE TO START TAPE
  55. TOFF    EQU    $3A6        ROUTINE TO STOP TAPE
  56. CURPOS    EQU    $37E        ROUTINE TO POSITION CURSOR
  57. SPACE    EQU    $144        DISPLAY SPACE ON CONSOLE
  58. NL    EQU    $35B        ROUTINE TO PRINT A <LF>, <CR> ON TERMINAL
  59. PMSG    EQU    $34E        DISPLAY'S MSG(HL) UP TO ZERO OR <CR>
  60. * MEMORY ALLOCATION
  61. BUFF    EQU    $1400        START OF RAM, INPUT BUFFER
  62. IOCON    EQU    BUFF+$FF    INPUT/OUTPUT CONFIGURATION
  63. USROUT    EQU    IOCON-2        USER SUPPLIED OUTPUT DEVICE VECTOR
  64. CURSOR    EQU    USROUT-2    CURSOR POSITION
  65. LSTCHR    EQU    CURSOR-2    CHARACTER UNDER CURSOR
  66. STACK    EQU    LSTCHR-2    MACHINE STACK
  67. TB    EQU    BUFF+50        TEMPORARY TEXT BUFFER
  68. XBF    EQU    TB+50        EXTRA TEXT BUFFER
  69. EDBUF    EQU    BUFF+256    EDIT BUFFER
  70. CS    EQU    EDBUF+$FA    CONTROL STACK SPACE
  71. CSP    EQU    CS+1        CONTROL STACK POINTER
  72. ARYLOC    EQU    CSP+2        LOCATION OF ARRAYS
  73. SEED    EQU    ARYLOC+1    RANDOM NUMBER SEED
  74. VARS    EQU    SEED+2        VARIABLE SPACE
  75. RFLAG    EQU    VARS+52        PROGRAM RUNNING FLAG
  76. IFLAG    EQU    RFLAG+1        INPUTTING FLAG
  77. P    EQU    IFLAG+1        POINTER TO END OF EXPRESSION
  78. EFLAG    EQU    P+1        ASSIGNMENT FLAG
  79. DATA    EQU    EFLAG+1        READ/DATA POINTER
  80. LAST    EQU    DATA+2        LAST FREE ARRAY SPACE
  81. TEMP    EQU    LAST+2        TEMPORARY STORAGE
  82. TEXT    EQU    VARS+1024    PROGRAM AND ARRAY STORAGE
  83. DELETE    EQU    $7F        DELETE CHARACTER
  84.     PAGE
  85. *
  86. ********************************************************************
  87. * START OF MAIN PROGRAM, FIRST INITIALIZE, INSURING WE DON'T THINK *
  88. * WE HAVE A VALID PROGRAM, ALSO CLEAR OUT HIS VARIABLES AND ARRAYS *
  89. ********************************************************************
  90. *
  91.     ORG    $400        FOLLOW MONITOR
  92. BASIC    MVI    A,$0C        CHARACTER TO CLEAR SCREEN
  93.     CALL    OUT        CLEAR VIDEO SCREEN
  94. NEW    MVI    A,$FF        INDICATES END OF PROGRAM
  95.     STA    TEXT        INITIALIZE TO NO PROGRAM
  96. RESV    CALL    CLEAR        CLEAR OUT HIS VARIABLES
  97. * RESET FLAGS, AND PROMPT WITH 'READY', SO HE WILL KNOW WE ARE LISTENING
  98. INIT    LXI    H,0        GET DOUBLE BYTE ZERO
  99.     SHLD    RFLAG        INDICATE NOT RUNNING, AND NOT INPUT
  100.     SHLD    P        INDICATE NO ASSIGNMENT DONE
  101.     LXI    H,RDY        ADDRESS OF 'READY' MESSAGE
  102.     CALL    PMSG        TELL HIM WE ARE READY
  103. * GET A LINE FROM CONSOLE, AND SEE WHAT HE WANTS
  104. TOP    LXI    SP,STACK    FIX UP STACK IN CASE WE ABORTED SOMETHING
  105.     CALL    GLINE        LET HIM GIVE US A LINE
  106.     CPI    $0D        DID HE ONLY PRESS RETURN
  107.     JZ    TOP        NOT GOOD ENOUGH, MAKE HIM TRY AGAIN
  108.     CALL    NUM        DID HIS LINE START WITH A NUMBER
  109.     JNC    EDIT        IF SO, HE IS WRITEING A PROGRAM!!!
  110. * LOOK UP COMMAND AND EXECUTE
  111.     LXI    B,INIT        ADDRESS TO RETURN TO
  112.     PUSH    B        SAVE SO WE CAN RETURN
  113.     LXI    H,KTAB-1    POINT TO COMMAND TABLE
  114. *
  115. * LOCATES COMMAND POINTED TO BY D-E IN THE COMMAND TABLE POINTED TO BY H-L
  116. * AND CHAINS TO THE COMMAND PROCESSING CODE FOR THAT COMMAND
  117. *
  118. CMD    CALL    PARSE1        ADVANCE TO NEXT CHARACTER
  119. TLP0    PUSH    D        SAVE POINTER TO START OF COMMAND
  120. CMDL    INX    H        ADVANCE IN TABLE
  121.     LDAX    D        GET DATA FROM COMMAND
  122.     CMP    M        COMPARE WITH TABLE CONTENTS
  123.     INX    D        ADVANCE IN COMMAND
  124.     JZ    CMDL        IF SAME, KEEP TESTING
  125. * DIDN'T MATCH, SEE IF IT'S END OF WORD (HIGH BIT SET)
  126.     ORI    $80        ARE WE AT END?
  127.     CMP    M        AND IS IT THIS ONE?
  128.     JZ    GOTCMD        IF SO, WE HAVE IT
  129. * WASN'T THAT ENTRY, KEEP LOOKING
  130.     SUB    A        SEE IT THIS IS END OF TABLE
  131.     CMP    M        ARE WE AT END?
  132.     JZ    GOTDEF        IF SO, WE WILL SAY WE FOUND
  133.     POP    D        RESTORE POINTER TO COMMAND
  134. CMD1    ORA    M        TEST FOR AT END OF TABLE ENTRY
  135.     INX    H        POINT TO NEXT
  136.     JP    CMD1        IF NO, KEEP LOOKING
  137.     INX    H        SKIP FIRST ADDRESS BYTE
  138.     JMP    TLP0        TEST THIS ENTRY
  139. * WE HIT THE END OF THE TABLE, ASSUME THE DEFAULT ADDRESS (LET)
  140. GOTDEF    DCX    D        BACKUP TO START OF WORD
  141. * WE MATCHED ALL THE WAY TO THE END OF A COMMAND WORD, GET IT'S ADDRESS
  142. GOTCMD    INX    H        POINT TO ADDRESS BYTE
  143.     MOV    C,M        SAVE TEMPORARY
  144.     INX    H        POINT TO NEXT ADDRESS BYTE
  145.     MOV    H,M        GET LOW ADDRESS
  146.     MOV    L,C        GET HIGH ADDRESS
  147.     XTHL            PLACE CODE ADDRESS ON STACK, REMOVE TRASH
  148.     JMP    PARSE1        SKIP TO NEXT NON-BLANK, AND CHAIN TO CODE
  149. *
  150. ****************************************************************
  151. *              ERROR CHECKING AND HANDLING CODE
  152. ****************************************************************
  153. *
  154. * VCHAR... TESTS FOR A VALID VARIABLE, SYNTAX ERROR IF NOT
  155. *
  156. VCHAR    CALL    CHAR        TEST VARIABLE
  157.     RNC            IF OK, GO BACK
  158. *
  159. * SYNTAX ERROR... HE'S NOT MAKEING ANY SENSE AT ALL
  160. * ISSUE NASTY MESSAGE TO STRAIGHTEN HIM OUT
  161. *
  162. SYNT    LXI    H,SYN        GET NASTY 'SYNTAX' MESSAGE
  163.     DCX    D        BACK UP IN SOURCE SO WE DONT SAY WRONG LINE
  164. *
  165. * ERROR STUFF... SOMETHING HAS GONE WRONG... TELL HIM THE BAD NEWS AND
  166. * QUIT ANYTHING THAT WE MAY HAVE STARTED, SO THAT THINGS CAN'T GET WORSE
  167. * ALSO, IF WE WERE RUNNING, GIVE HIM THE LINE NUMBER AS A CLUE
  168. *
  169. ERR    MVI    A,'?'        PRECEDE ERROR MESSAGE BY '?'
  170.     CALL    OUT        DISPLAY ON TERMINAL
  171.     LDA    IFLAG        WERE WE TRYING TO 'INPUT' SOMETHING
  172.     ANA    A        IF WE WERE, THEN ..
  173.     JNZ    INERR        SPECIAL MESSAGE + HANDLEING
  174. * NOW THAT WE HAVE FIGURED OUT WHAT'S GOING ON, LET HIM IN ON IT
  175.     CALL    PMSG        PRINT ERROR MESSAGE
  176.     LXI    H,EM        FOLLOWED BY..
  177. * PRINT MESSAGE FOLLOWED BY LINE NUMBER (ALSO USED BY 'STOP IN LINE XXXX')
  178. PERR    CALL    PMSG        THE ' ERROR ' PART
  179.     LDA    RFLAG        WERE WE RUNNING..
  180.     ANA    A        IF NOT,
  181.     JZ    INLF        THEN THATS ALL WE HAVE TO DO
  182. * DISPLAY LINE NUMBER OF RUNNING PROGRAM
  183.     LXI    H,INL        ADDRESS OF 'IN LINE ' MESSAGE
  184.     CALL    PMSG        DISPLAY FOR HIM
  185. * FIND START OF OUR LINE, AND DISPLAY LINE NUMBER
  186. FSOL    DCX    D        BACK UP IN SOURCE
  187.     MOV    A,D        GET HIGH BYTE OF ADDRESS
  188.     CPI    =TEXT        TEST FOR BEYOND BEGINNING
  189.     JC    STLIN        AT START OF LINE
  190.     LDAX    D        GET CHARACTER FROM BUFER
  191.     CPI    $0D        TEST FOR CARRIAGE RETURN
  192.     JNZ    FSOL        IF NOT, KEEP LOOKING
  193. STLIN    INX    D        ADVANCE IN SOURCE
  194.     XCHG            SWAP TO H-L FOR PNUM
  195.     CALL    PNUM        PRINT AND BUFFER LINE NUMBER
  196. * COPY LINE WITH ERROR INTO OLD LINE EDIT BUFFER, INCASE HE WANTS TO FIX IT
  197. FIXIT    INX    H        SKIP LENGTH BYTE, ADVANCE TO NEXT IN SOURCE
  198.     MOV    A,M        GET CHARACTER FROM LINE
  199.     STAX    D        SAVE IN BUFFER
  200.     INX    D        ADVANCE TO NEXT IN BUFFER
  201.     CPI    $0D        TEST FOR END-OF-LINE
  202.     JNZ    FIXIT        IF NOT, KEEP COPYING
  203. * WAIT FOR CONSOLE INPUT, ON A NEW LINE
  204. INLF    CALL    NL        ADVANCE A LINE ON HIS TERMINAL
  205.     CALL    RESET        RESET DATA POINTER AND CONTROL-STACK
  206.     JMP    INIT        GET NEXT COMMAND
  207. *
  208. * SUBROUTINE TEST FOR VALID ASCII DIGIT (0-9), RETURNS WITH C=1 IF NOT
  209. *
  210. NUM    CPI    '0'        TEST FOR < '0'
  211.     RC            IF SO, BAD DIGIT
  212.     CPI    $3A        TEST FOR >'9'
  213.     CMC            INVERT LOGIC, C=1 IF BAD
  214.     RET
  215. *
  216. ****************************************************************
  217. *                    TEXT EDITING ROUTINES
  218. ****************************************************************
  219. *
  220. * SUBROUTINE TO GET AND EDIT COMMAND LINE FROM TERMINAL
  221. *
  222. BADLN    CALL    NL        ADVANCE TO NEW LINE
  223. GLINE    LXI    D,BUFF        POINT TO INPUT BUFFER
  224.     LXI    H,EDBUF        POINT TO EDIT BUFFER
  225.     MOV    B,E        CLEAR INSERT FLAG (LOW ADR OF BUFFER IS ZERO)
  226. LOOP1    MOV    A,E        GET LOW ADDRESS OF OUR POSITION
  227.     ANA    A        TEST FOR NEGATIVE
  228.     JM    BADLN        IF SO, HE'S DELETED BEYOND START OF BUFFER
  229.     CALL    IN        GET A CHARACTER
  230.     CPI    3        TEST FOR CONTROL-C (CANCEL)
  231.     JZ    INLF        IF SO, ABORT BACK TO COMMAND HANDLER
  232.     CPI    6        TEST FOR CONTROL-F (FIND COMMAND)
  233.     JZ    GFIND        EXECUTE FIND
  234.     CPI    1        TEST FOR CONTROL-A (ADVANCE COMMAND)
  235.     JZ    GADV        EXECUTE ADVANCE
  236.     CPI    9        TEST FOR CONTROL-I (TOGGLE INSERT MODE)
  237.     JZ    GINST        TOGGLE INSERT MODE
  238.     CPI    4        TEST FOR CONTROL-D (DELETE CHARACTER.)
  239.     JZ    GRUB        ERASE CHARACTER
  240.     CPI    ' '        TEST FOR CONTROL-CHARACTER
  241.     JNC    OKPRT        IF NOT, OK TO PROCESS
  242.     CPI    $0D        CARRIAGE RETURN IS OK,
  243.     JZ    OKPRT        SO PROCESS IT
  244.     CPI    8        SO IS A BACKSPACE
  245.     JNZ    LOOP1        ANYTHING ELSE SHOULD BE IGNORED
  246. * WE HAVE GOTTEN A VALID CHARACTER
  247. OKPRT    CPI    DELETE        TEST FOR DELETE CHARACTER
  248.     JNZ    RECT        IF IT IS A DELETE,
  249.     MVI    A,8        MAKE IT INTO A BACKSPACE
  250. RECT    MOV    C,A        COPY INTO C
  251.     CALL    OUT        DISPLAY ON TERMINAL
  252.     DCX    D        ASSUME DELETE (BACKSPACE)
  253. * DON'T DELETE CHARS FROM OLD LINE BUFFER IF WE ARE INSERTING
  254.     ORA    B        TEST INSERT FLAG
  255.     JM    IND        IF NOT, WE ARE INSERTING
  256.     DCX    H        REDUCE OLD BUFFER POSITION
  257. IND    MOV    A,C        GET CHARACTER BACK
  258.     CPI    8        TEST FOR DELETE (BACKSPACE)
  259.     JZ    LOOP1        IF SO, WE WERE RIGHT, GET NEXT CHARACTER
  260.     INX    D        FIX OUR MISTAKE (NOT DELETE)
  261.     STAX    D        SAVE CHARACTER IN BUFFER
  262. * DON'T MOVE OLD LINE POINTER IF WE ARE INSERTING
  263.     ORA    B        TEST INSERT FLAG
  264.     JM    INOK        IF SO, DON'T INCREMENT
  265.     INX    H        ADVANCE IN OLD LINE BUFFER
  266.     MOV    A,M        GET CHARACTER FROM OLD LINE
  267.     CPI    $0D        TEST FOR END OF OLD LINE
  268.     JZ    INOK        IF SO, DON'T GO PAST IT
  269.     INX    H        ADVANCE TO NEXT CHARACTER OF OLD LINE
  270. INOK    MOV    A,C        GET CHARACTER BACK
  271.     INX    D        ADVANCE POINTER IN NEW LINE
  272.     CPI    $0D        TEST FOR CARRAIGE RETURN (END OF LINE)
  273.     JNZ    LOOP1        IF NOT, KEEP GETTING CHARACTERS
  274.     CALL    NL        PRINT LINE-FEED CARRIAGE RETURN
  275. * COPY NEW LINE INTO OLD LINE BUFFER (MAKEING IT THE 'NEW' OLD LINE)
  276.     LXI    D,BUFF        POINT BACK TO NEW LINE BUFFER
  277.     PUSH    D        SAVE BUFFER ADDRESS
  278.     LXI    H,EDBUF        POINT TO OLD LINE BUFFER
  279. MOVL    LDAX    D        GET CHARACTER FROM NEW LINE
  280.     MOV    M,A        SAVE IN OLD LINE BUFFER
  281.     INX    H        POINT TO NEXT
  282.     INX    D        POINT TO NEXT
  283.     CPI    $0D        TEST FOR END OF LINE
  284.     JNZ    MOVL        IF NOT, KEEP MOVEING
  285.     POP    D        RESTORE BUFFER ADDRESS
  286.     LDAX    D        AND FIRST CHARACTER FROM IT
  287.     RET
  288. * COPY ONE CHARACTER FROM OLD LINE TO NEW LINE
  289. GADV    MOV    A,M        GET CHARACTER FROM OLD LINE
  290.     CPI    $0D        INSURE ITS NOT THE END
  291.     JZ    LOOP1        IF SO, IGNORE COMMAND
  292.     ORA    B        TEST INSERT FLAG
  293.     MOV    A,M        GET CHARACTER BACK
  294.     JP    RECT        IF NO INSERT, OK
  295.     INX    H        ADVANCE TO NEXT
  296.     JMP    RECT        PASS CHARACTER TO INPUT ROUTINE
  297. * RUB OUT ONE CHARACTER FROM THE OLD LINE
  298. GRUB    MOV    A,M        GET CHARACTER FROM OLD LINE
  299.     CPI    $0D        TEST FOR END OF LINE
  300.     JZ    LOOP1        IF SO, IGNORE COMMAND
  301.     MVI    A,'*'        INDICATE RUBBED OUT CHARACTER WITH '*'
  302.     CALL    OUT        PRINT  IT TO SHOW WHAT WE ARE DOING
  303.     INX    H        ADVANCE PASSED CHARACTER (RUBBING IT OUT)
  304.     JMP    LOOP1        RETURN FOR NEXT CHARACTER
  305. * FIND NEXT CHARACTER IN NEW LINE
  306. GFIND    CALL    IN        GET A CHARACTER
  307.     MOV    C,A        SAVE IN C (TO COMPARE AGAINST.)
  308.     PUSH    H        SAVE POSITION IN OLD LINE
  309. * FIND OUT IF IT IS THERE..
  310. GF1    MOV    A,M        GET CHARACTER FROM OLD LINE
  311. GF0    CPI    $0D        TEST FOR END OF LINE
  312.     JZ    ABFND        IF SO, WE DIDN'T FIND IT
  313.     INX    H        ADVANCE TO NEXT CHARACTER
  314.     MOV    A,M        GET CHARACTER
  315.     CMP    C        TEST FOR CHARACTER WE DESIRE
  316.     JNZ    GF0        IF NOT, KEEP LOOKING
  317.     POP    H        RESTORE POSITION ON OLD LINE
  318. * NOW COPY OLD LINE OVER..
  319. GF2    MOV    A,M        GET CHARACTER FROM OLD LINE
  320. GF3    STAX    D        SAVE IN NEW LINE
  321.     CALL    OUT        DISPLAY ON TERMINAL
  322.     INX    H        POINT TO NEXT CHAR. IN OLD LINE
  323.     INX    D        POINT TO NEXT CHAR IN NEW LINE
  324.     MOV    A,M        GET NEXT CHAR FROM NEW LINE
  325.     CMP    C        TEST FOR CHARACTER WE WANT
  326.     JNZ    GF3        IF NOT, KEEP COPYING
  327.     PUSH    H        FIX UP STACK
  328. ABFND    POP    H        RESTORE POSITION IN OLD LINE
  329.     JMP    LOOP1        GET NEXT CHARACTER
  330. * TOGGLE INSERT MODE
  331. GINST    MOV    A,B        GET INSERT MODE FLAG
  332.     XRI    $FF        COMPLEMENT, SETTING FLAGS
  333.     MOV    B,A        REAVE IN FLAG REGISTER
  334.     MVI    A,'<'        INDICATE ENTERING INSERT MODE
  335.     JM    GIN1        IF SO, INDICATE SO
  336.     MVI    A,'>'        INDICATE LEAVING INSERT
  337. GIN1    CALL    OUT        DISPLAY INDICATOR ON TERMINAL
  338.     JMP    LOOP1        GET NEXT CHARACTER FROM TERMINAL
  339. *
  340. * GET A PACKED-DECIMAL LINE NUMBER FROM THE COMMAND BUFFER
  341. *
  342. GETLN    LXI    H,0        START WITH ZERO
  343. ELOOP    LDAX    D        GET DIGIT FROM COMMAND BUFFER
  344.     CALL    NUM        TEST FOR ASCII DIGIT
  345.     RC            IF NOT, STOP (WE HAVE IT)
  346.     INX    D        ADVANCE TO NEXT BUFFER POSITION
  347.     DAD    H        MAKE ROOM FOR DIGIT IN BOTTOM..
  348.     DAD    H        OF THE RESULT, BY ..
  349.     DAD    H        ROTATING IT..
  350.     DAD    H        LEFT BY FOUR BITS
  351.     ANI    $0F        CONVERT DIGIT TO BINARY
  352.     ORA    L        INSERT INTO LOWER DIGITS OF RESULT
  353.     MOV    L,A        AND REPLACE BYTE IN RESULT WITH NEW VALUE
  354.     JMP    ELOOP        GET NEXT DIGIT
  355. *
  356. * LINE EDITOR, EDITS PROGRAM SOURCE BY LINE NUMBER IN COMMAND BUFFER
  357. *
  358. EDIT    CALL    LINEF        LOCATE LINE NUMBER IN SOURCE
  359.     PUSH    H        SAVE POINTER INTO TEXT
  360.     JNZ    INS        IF NEW LINE, DON'T TRY TO DELETE
  361. * DELETE LINE POINTED TO BY H-L
  362. DEL    MOV    D,H        COPY POINTER INTO
  363.     MOV    E,L        THE D-E PAIR FOR BACKWARDS COPY
  364.     MVI    A,$0D        WE ARE LOOKING FOR A CARRIAGE RETURN
  365. * FIND START OF NEXT LINE
  366. DELNX    CMP    M        TEST FOR END OF LINE TO DELETE
  367.     INX    H        POINT TO NEXT CHARACTER IN SOURCE
  368.     JNZ    DELNX        IF NOT END OF LINE, KEEP LOOKING
  369. * COPY REST OF PROGRAM BACK OVER DELETED LINE
  370. DELLP    MOV    A,M        GET CHARACTER FROM NEXT LINE
  371.     STAX    D        SAVE OVER DELETED LINE
  372.     INX    D        POINT TO NEXT IN NEW LINE
  373.     INX    H        POINT TO NEXT IN OLD LINE
  374.     INR    A        TEST FOR END OF FILE
  375.     JNZ    DELLP        IF NOT, KEEP DELETEING
  376. * INSERT LINE INTO TEXT
  377. INS    LXI    B,2        SET LENGTH TO 2 (PACKED DECIMAL NUMBERS ARE 2)
  378.     LXI    D,BUFF        POINT TO BUFFER (CONTAINING NEW LINE)
  379. * CALCULATE LENGTH OF LINE
  380.     CALL    GETLN        REMOVE NUMBERS AS THEY ARE NOT STORED AS TEXT
  381. ILP    INR    C        INCREMENT LENGTH
  382.     LDAX    D        GET CHARACTER FROM NEW LINE (IN BUFFER)
  383.     INX    D        POINT TO NEXT CHARACTER FROM NEW LINE
  384.     CPI    $0D        TEST FOR END OF LINE
  385.     JNZ    ILP        IF NOT, KEEP COUNTING
  386.     MOV    A,C        GET LENGTH
  387.     POP    H        RESTORE POSITION IN TEXT
  388.     CPI    3        TEST FOR NULL LINE
  389.     JZ    TOP        IS SO, DON'T INSERT
  390. * INSERT NEW LINE INTO TEXT
  391. INLN    MOV    D,H        SET D-E TO POINT TO
  392.     MOV    E,L        THE LINE POSITION
  393.     CALL    GETEOF        GET END OF FILE ADDRESS
  394.     INX    H        ADVANCE TO FREE BYTE
  395.     PUSH    B        SAVE LENGTH
  396.     PUSH    H        STACK END OF FILE ADDRESS
  397.     DAD    B        ADD LENGTH
  398.     POP    B        GET END OF FILE ADDRESS
  399.     INX    H        ADVANCE BECAUSE WE DECREMENT
  400. IL01    DCX    H        REDUCE POINTER INTO NEW POSITION
  401.     DCX    B        REDUCE POINTER TO OLD POSITION
  402.     LDAX    B        GET BYTE OF OLD DATA
  403.     MOV    M,A        SAVE IN NEW POSITION
  404.     MOV    A,C        GET LOW ADDRESS
  405.     CMP    E        TEST AGAINST WHERE WE ARE GOING
  406.     JNZ    IL01        IF NOT, KEEP COPYING
  407.     MOV    A,B        GET HIGH ADDRESS
  408.     CMP    D        TEST AGAINST DESTINATION
  409.     JNZ    IL01        IF NOT SAME, KEEP COPYING
  410.     LXI    D,BUFF        GET ADDRESS OF NEW LINE
  411.     CALL    GETLN        OBTAIN NUMBERS
  412.     MOV    A,H        GET HIGH 2 DIGITS
  413.     STAX    B        SAVE IN NEW LINE
  414.     INX    B        POINT TO NEXT CHARACTER OF NEW LINE
  415.     MOV    A,L        GET LOW DIGITS
  416.     STAX    B        SAVE IN NEW LINE
  417.     INX    B        ADVANCE TO NEXT CHARACTER IN NEW LINE
  418.     POP    H        RESTORE LENGTH
  419.     MOV    A,L        GET LENGTH
  420.     ADI    $10        ADD OFFSET TO MAKE UNIQUE
  421.     STAX    B        SAVE IN NEW LINE
  422.     INX    B        POINT TO NEXT CHARACTER
  423. IL02    LDAX    D        GET CHARACTER FROM NEW LINE IN BUFFER
  424.     STAX    B        SAVE IN TEXT
  425.     INX    B        POINT TO NEXT POSITION IN TEXT
  426.     INX    D        ADVANCE IN BUFFER
  427.     CPI    $0D        TEST FOR END OF LINE
  428.     JNZ    IL02        IF NOT, KEEP LOOKING
  429. * WE ARE INSERTING OR REPLACEING A LINE, SINCE WE DON'T KNOW HOW MUCH
  430. * MEMORY IT WILL REQUIRE, WE MUST CLEAR THE ARRAYS, AS THEY FOLLOW THE
  431. * PROGRAM. WE DO NOT HAVE TO DO THIS WHEN DELETING LINES
  432.     CALL    CLRARY        CLEAR ARRAYS AND RETURN
  433.     JMP    TOP        GO BACK FOR NEXT COMMAND
  434. *
  435. * LOCATE LINE IN TEXT, SYNTAX ERROR IF NOT LINE NUMBER
  436. *
  437. FNDLIN    CALL    NUM        IS IT A VALID NUMBER
  438.     JC    SYNT        IF NOT, IT'S A INVALID
  439. *
  440. * FINDS LINE IN PROGRAM TEXT. RETURNS WITH Z FLAG SET IF LINE EXISTS
  441. * H-L POINTS TO START OF LINE. B-C CONTAINS LINE NUMBER OF ACTUAL
  442. * LINE FOUND. (IF LINE NOT FOUND, POINTS TO FIRST GREATER LINE NUMBER)
  443. *
  444. LINEF    CALL    GETLN        GET LINE NUMBER FROM COMMAND BUFFER
  445.     XCHG            SWAP TO D-E
  446.     LXI    H,TEXT        START AT TOP OF PROGRAM
  447. TRY    MOV    A,M        GET FIRST CHARACTER FROM PROGRAM LINE
  448.     CPI    $FF        TEST FOR END OF FILE
  449.     JZ    EOF        IF SO, WE DIDN'T FIND
  450.     INX    H        ADVANCE POINTER TO LOW DIGITS
  451.     CMP    D        TEST FOR HIGH DIGITS CORRECT
  452.     JC    NEXTL        IF LESS, FIND NEXT LINE
  453.     JNZ    NOTFND        IF GREATER, LINE WASN'T FOUND
  454.     MOV    A,M        GET LOW DIGITS
  455.     CMP    E        TEST LOW DIGITS
  456.     JNC    NOTFND        IF LESS, LINE IS HERE OR DOSN'T EXIST
  457. * ADVANCE TO NEXT LINE IN SOURCE
  458. NEXTL    INX    H        POINT TO LINE LENGTH
  459.     MOV    A,M        GET LENGTH
  460.     SUI    $11        SUBTRACT OFFSET USED TO MAKE IT UNIQUE
  461.     ADD    L        ADD TO POINTER
  462.     MOV    L,A        AND REPLACE IN POINTER
  463.     JNC    TRY        IF NO CARRY, THATS IT
  464.     INR    H        BUMP HIGH ADDRESS
  465.     JMP    TRY        AND TEST THIS LINE
  466. * LINE IS HERE OR BEFORE
  467. NOTFND    DCX    H        BACK UP TO DIGIT
  468.     MOV    C,A        PLACE LOW ORDER DIGIT IN C
  469.     MOV    B,M        PLACE HIGH ORDER DIGIT IN B
  470.     CMP    E        TEST FOR LINE FOUND
  471.     RNZ            IF NOT SAME, RETURN INDICATING SO
  472.     MOV    A,B        GET HIGH DIGIT
  473.     CMP    D        INDICATE IF NUMBERS SAME
  474.     RET
  475. * LINE WAS GREATER THAN ALL LINES IN PROGRAM, INDICATE EOF REACHED
  476. EOF    MOV    B,A        RETURN HIGH LINE NUMBER
  477.     ANA    A        INDICATE LINE DOSN'T EXIST
  478.     RET
  479. *
  480. * PRINTS PACKED-DECIMAL LINE NUMBER ON TERMINAL, AS WELL AS PLACEING
  481. * IT AT THE START OF THE EDIT BUFFER
  482. *
  483. PNUM    LXI    D,EDBUF        SET UP POINTER TO EDIT BUFFER
  484.     CALL    HPOUT        PRINT FIRST TWO DIGITS
  485. HPOUT    MOV    A,M        GET CONTENTS OF MEMORY
  486.     INX    H        AND POINT TO NEXT
  487.     PUSH    PSW        SAVE FOR LATER
  488.     RRC            ROTATE
  489.     RRC            UPPER DIGIT
  490.     RRC            INTO
  491.     RRC            LOWER DIGIT
  492.     CALL    POUT        DISPLAY UPPER DIGIT
  493.     POP    PSW        GET LOWER DIGIT BACK
  494. * DISPLAYS ONE DIGIT
  495. POUT    ANI    $0F        REMOVE UPPER GARBAGE
  496.     ORI    $30        CONVERT TO ASCII DIGIT
  497.     STAX    D        SAVE IN EDIT BUFFER
  498.     INX    D        ADVANCE POINTER IN EDIT BUFFER
  499.     JMP    OUT        DISPLAY DIGIT ON TERMINAL AND RETURN
  500. *
  501. ******************************************************************
  502. *                   BASIC COMMAND HANDLERS
  503. ******************************************************************
  504. *
  505. * IT'S A 'LIST' COMMAND, LETS GIVE HIM A PEEK AT THE SOURCE
  506. * ALSO PLACE LAST LINE LISTED IN BUFFER, INCASE HE WANTS TO EDIT IT
  507. *
  508. LIST    PUSH    D        SAVE PROGRAM POINTER
  509.     LXI    H,TEXT        START AT THE BEGINNING OF THE PROGRAM
  510.     MVI    B,255        SET ENDING LINE BEYOND END OF TEXT
  511.     LDAX    D        GET CHARACTER OF OPERAND
  512.     CALL    NUM        TEST FOR A NUMBER
  513.     JC    GO        IF NOT, LIST WHOLE THING
  514.     CALL    GETLN        GET LINE NUMBER
  515.     PUSH    H        SAVE ON STACK
  516.     INX    D        POINT TO NEXT CHARACTER
  517.     CPI    ','        TEST FOR ENDING NUMBER
  518.     CZ    LINEF        IF SO, GET ENDING NUMBER
  519.     INX    H        ADVANCE PAST BEGINNING OF LINE
  520.     POP    D        GET STARTING LINE NUMBER BACK
  521.     PUSH    H        SAVE ENDING LINE
  522.     CALL    LINEF+4        FIND STARTING LINE ADDRESS
  523.     POP    B        GET ENDING ADDRESS BACK
  524. * LIST TEXT FROM STARTING LINE IN H-L TO ENDING LINE IN B-C
  525. GO    MOV    A,M        GET CHARACTER FROM START OF LINE
  526.     INR    A        TEST FOR END OF FILE
  527.     JZ    LIRET        IF SO, STOP LISTING
  528.     CALL    PNUM        DISPLAY LINE NUMBER AND BUFFER IT
  529.     INX    H        SKIP LENGTH BYTE, AS IT DOSN'T LOOK PRETTY
  530. PRINS    MOV    A,M        GET CHARACTER FROM LINE
  531.     STAX    D        PLACE INTO BUFFER
  532.     INX    D        ADVANCE IN BUFFER
  533.     CALL    OUT        DISPLAY ON TERMINAL
  534.     INX    H        ADVANCE POINTER IN PROGRAM
  535.     CPI    $0D        TEST FOR END OF LINE
  536.     JNZ    PRINS        IF NOT, KEEP PRINTING
  537.     CALL    NL        NEW LINE ON TERMINAL
  538.     CALL    COMP        TEST FOR LAST LINE LISTED
  539.     JNC    LIRET        IF SO, STOP LISTING
  540.     CALL    CTRLC        TEST FOR ABORT FROM TERMINAL
  541.     JNZ    GO        KEEP LISTING IF NOT
  542. LIRET    POP    D        RESTORE PROGRAM POINTER
  543.     RET
  544. *
  545. * CLEARS VARIABLES AND ARRAYS. (INITIALIZES THEM) AND INITIALIZES EDIT BUFFER
  546. *
  547. CLEAR    LXI    H,VARS        POINT TO VARIABLE SPACE
  548.     MVI    A,$0D        GET A CARRIAGE RETURN (END OF LINE CHARACTER)
  549.     STA    EDBUF        INITIALIZE EDIT BUFFER TO A NULL LINE
  550.     MVI    C,52        26 VARIABLE TIMES 2 BYTES/VARIABLE
  551. CVLP    MVI    M,0        CLEAR INTEGER VARAIBLES TO ZERO
  552.     INX    H        ADVANCE TO NEXT BYTE OF VARIABLE SPACE
  553.     DCR    C        REDUCE COUNT OF VARAIABLES LEFT
  554.     JNZ    CVLP        KEEP GOING TILL ALL INTEGERS ARE ZERO'ED
  555.     MVI    A,=VARS+$400    ADDRESS OF END OF VARIABLE TABLE
  556.     LXI    B,10        SKIP AHEAD 10 BYTES
  557.     DAD    B        SO THAT WE DON'T CLOBBER OUR FLAGS
  558. CVL1    MVI    M,255        $FF IS NULL CHARACTER FOR CHAR. VARS
  559.     INX    H        POINT TO NEXT BYTE IN CHAR. VAR. SPACE
  560.     CMP    H        TEST FOR COMPLETE (ALL SET TO NULL STRINGS)
  561.     JNZ    CVL1        KEEP GOING TILL WE DO THEM ALL
  562. * INITIALIZE ARRAYS, RESET ARRAY SPACE TO FIRST PAGE FOLLOWING PROGRAM
  563. CLRARY    CALL    GETEOF        GET ADDRESS OF FIRST FREE PAGE+SET POINTER
  564.     STA    ARYLOC        STASH IN ARRAY TABLE POINTER
  565.     MOV    H,A        PLACE IN H, SO WE CAN REFERENCE INDERECT
  566.     MVI    L,52        START AT END OF TABLE
  567.     SHLD    LAST        INDICATE FREE SPACE FOR NEXT ARRAY
  568.     SUB    A        GET A ZERO
  569. CALS    DCR    L        BACK UP IN TABLE
  570.     MOV    M,A        INITIALIZE TO INDICATE NO ARRAY
  571.     JNZ    CALS        KEEP GOING TILL TABLE IS CLEARED
  572. * RESET CONTROL STACK AND DATA POINTER
  573. RESET    LXI    H,CS        GET USER STACK POINTER
  574.     SHLD    CSP        INITIALZE USER STACK POINTER
  575.     LXI    H,0        GET A ZERO (NO DATA POINTER)
  576.     SHLD    DATA        INSURE NO DATA PRESENT
  577.     RET
  578. *
  579. * ** WE'VE GOTTEN A 'RUN' COMMAND, LETS START THE PROGRAM ROLLING **
  580. *
  581. RUN    LDA    TEXT        GET FIRST CHARACTER OF PROGRAM
  582.     LXI    H,NP        AND ADDRESS OF 'NO PROGRAM' MESSAGE
  583.     INR    A        TEST FOR EXISTANCE OF PROGRAM
  584.     JZ    ERR        IF NOT, POINT OUT HIS MISTAKE
  585.     CALL    CLEAR        CLEAR VARIABLES AND ARRAYS
  586.     LXI    D,TEXT        START INTERPRETING AT THE BEGINNING
  587. RGON    MVI    A,255        INDICATE THAT WE ARE RUNNING
  588.     STA    RFLAG        BY SETTING THIS FLAG
  589. RNEWL    INX    D        SKIP PACKED DECIMAL LINE
  590.     INX    D        NUMBERS, AND THE LENGTH BYTE,
  591.     INX    D        AS THE COMMAND FINDER WON'T LIKE IT
  592. * MAIN 'RUN' INTERPRETING LOOP
  593. RLOOP    LXI    SP,STACK    REPAIR ANY DAMAGE
  594.     CALL    CTRLC        TEST FOR 'MAGIC' CONTROL-C CHARACTER
  595.     JZ    STOP        IF SO, FAKE A 'STOP' COMMAND
  596.     LXI    H,PTAB-1    POINT TO PROGRAM COMMAND TABLE
  597.     CALL    CMD        RUN PROGRAM CODE
  598. * ADVANCE TO NEXT STATEMENT
  599. RNEXT    LDAX    D        GET CHARACTER FROM SOURCE
  600.     CPI    $22        TEST FOR A QUOTE
  601.     CZ    SKPQUO        IF SO, SEARCH FOR NEXT ONE
  602.     INX    D        ADVANCE TO NEXT CHARACTER
  603.     CPI    ':'        TEST FOR COLON (NEW STATEMENT)
  604.     JZ    RLOOP        IF SO, EXECUTE NEXT COMMAND
  605.     CPI    $0D        TEST FOR CARRIAGE RETURN
  606.     JNZ    RNEXT        IF NOT, KEEP LOOKING
  607.     LDAX    D        GET FIRST CHAR OF NEW LINE
  608.     INR    A        TEST FOR $FF (END OF FILE)
  609.     JZ    INIT        IF SO, GO BACK TO COMMAND MODE
  610.     JMP    RNEWL        EXECUTE THIS LINE
  611. *
  612. * EITHER WE HAVE GOTTEN A 'STOP' COMMAND, OR THE OPERATOR PRESSED
  613. * CONTROL-C, EITHER WAY, PRINT THE MESSAGE AND EXIT
  614. *
  615. STOP    LXI    H,STMSG        ADDRESS OF 'STOP' MESSAGE
  616.     JMP    PERR        TREAT IT LIKE AN ERROR
  617. * IT'S A 'THEN', FOLLOWING AN 'IF', LOOK FOR LINE NUMBER OR A STATEMENT
  618. THEN    CALL    NUM        IS IT A NUMBER?
  619.     JNC    GOTO        IF SO, ITS A NUMBER TO 'GOTO'
  620.     JMP    RLOOP        IF NOT, ITS A STATEMENT TO EXECUTE
  621. *
  622. * IT'S A 'GOSUB' SAVE RETURN ADDRESS, AND PRETEND IT'S 'GOTO'
  623. *
  624. GOSUB    CALL    PUSHD        SAVE SOURCE POSITION
  625.     SUB    A        INDICATE GOSUB ENTRY
  626.     CALL    PUSHS        SAVE ON USER STACK
  627.     LDAX    D        RESTORE OPERAND CHARACTER
  628. *
  629. * IT'S A 'GOTO' MAKE THE BIG JUMP
  630. *
  631. GOTO    CPI    '('        TEST FOR COMPUTED GOTO
  632.     JNZ    NOON        IF NO, NOT AN 'ON' STATEMENT
  633.     CALL    EXPR        GET VALUE OF INTERNAL EXPRESSION
  634. GLPO    CALL    SKIP        SKIP TO NEXT EXPRESSION
  635.     CPI    ','        IF THERE IS NO MORE COMMA'S
  636.     JNZ    SYNT        THEN WE RAN OUT OF OPERANDS
  637. GLPD    INX    D        SKIP THE COMMA
  638.     DCR    L        REDUCE OUR COUNT
  639.     JP    GLPO        IF IT'S STILL POSITIVE, KEEP SKIPPING
  640.     LDAX    D        GET CHARACTER FROM SOURCE
  641.     CPI    ' '        TEST FOR BLANKS
  642.     JZ    GLPD        AND KEEP GOING TILL WE SKIP THEM
  643. NOON    PUSH    D        SAVE POSITION (IN CASE WE FAIL)
  644.     CALL    FNDLIN        FIND THE LINE HE WANTS
  645.     POP    D        RESTORE OUR POSITION
  646.     XCHG            SWAP NEW POS INTO D-E
  647.     JZ    RGON        IF SUCESS, GOTO NEW LINE
  648.     XCHG            SWAP BACK
  649. *
  650. * OH OH, LOOKS LIKE HE'S TRIED TO GOTO, GOSUB OR ORDER TO A LINE HE FORGOT
  651. * TO TYPE IN, TELL HIM ABOUT IT AND LET HIM TRY TO FIGURE IT OUT
  652. *
  653. BADLIN    LXI    H,LIN        ADDRESS OF 'LINE NUMBER' MESSAGE
  654.     JMP    ERR        HANDLE LIKE ANY ERROR
  655. *
  656. * IT'S A 'RETURN', HOPE SOMEBODY DID A 'GOSUB' SOMEWHERE
  657. *
  658. RETURN    CALL    POPS        GET TYPE OF STACK ENTRY
  659.     ANA    A        TEST FOR 'GOSUB' ENTRY
  660.     JZ    POPD        IF SO, GET ADDRESS BACK AND RETURN
  661. *
  662. * HE SCREWED UP THE FOR/NEXT, GOSUB/RETURN NESTING
  663. * LET HIM IN ON IT AND DIE WHILE WE CAN
  664. *
  665. NSTERR    LXI    H,CSTK        ADDRESS OF 'NESTING' MESSAGE
  666.     JMP    ERR        HANDLE LIKE ANY ERROR
  667. *
  668. * IT'S A 'FOR' COMMAND, LETS THROW THIS THING FOR A LOOP
  669. *
  670. FOR    CALL    VCHAR        INSURE IT'S A VARIABLE
  671.     PUSH    PSW        SAVE IT (IT'S THE LOOP INDEX VARIABLE)
  672.     DCX    D        BACK UP POINT JUST BEFORE EXPRESSION
  673.     MOV    A,E        GET LOW ADDRESS
  674.     STA    P        AND PLACE IN POSITION FLAG
  675. FINTO    LDAX    D        GET CHARACTER FROM SOURCE
  676.     CPI    $0D        TEST FOR END OF LINE
  677.     JZ    SYNT        IF SO, HE'S GOOFED
  678.     INX    D        SKIP TO NEXT
  679.     CPI    'T'        TEST FOR A 'T'
  680.     JNZ    FINTO        IF NOT, WE ARN'T THERE YET
  681.     LDAX    D        GET NEXT CHARACTER
  682.     CPI    'O'        IS IT 'TO'
  683.     JNZ    FINTO        NO, MUST BE VARIABLE 'T'
  684.     PUSH    D        SAVE OUR POSITION
  685.     DCX    D        BACKUP TO THE 'T'
  686.     CALL    DOEXP        EVALUATE EXPRESSION
  687.     POP    D        RESTORE OUT POSITION
  688.     INX    D        SKIP 'O'
  689.     CALL    EXPR        GET LIMIT EXPRESSION
  690.     CALL    PUSHD        SAVE OUR POSITION ON STACK
  691.     XCHG            GET LIMIT VALUE
  692.     CALL    PUSHD        SAVE ON STACK
  693.     XCHG            GET POSITION BACK
  694.     POP    PSW        GET INDEX VARIABLE NAME
  695. *
  696. * SAVES A SINGLE BYTE ENTRY ON THE USER (CONTROL) STACK
  697. *
  698. PUSHS    PUSH    H        SAVE H-L
  699.     LHLD    CSP        GET STACK POINTER
  700.     MOV    M,A        SAVE BYTE ON STACK
  701. PSH1    DCX    H        REDUCE POINTER
  702. PSH2    SHLD    CSP        RESAVE STACK POINTER
  703.     POP    H        RESTORE H-L
  704.     RET
  705. *
  706. * POP A SINGLE BYTE ENTRY FROM THE USER (CONTROL) STACK
  707. *
  708. POPS    PUSH    H        SAVE H-L
  709.     LHLD    CSP        GET STACK POINTER
  710.     INX    H        ADVANCE TO NEXT ENTRY
  711.     MOV    A,M        GET BYTE BACK
  712.     JMP    PSH2        SAVE POINTER AND CONTINUE
  713. *
  714. * PUSHES A DOUBLE BYTE ENTRY ON THE USER (CONTROL) STACK
  715. *
  716. PUSHD    PUSH    H        SAVE H-L
  717.     LHLD    CSP        GET STACK POINTER
  718.     MOV    M,D        SAVE HIGH BYTE
  719.     DCX    H        BACK UP
  720.     MOV    M,E        SAVE LOW BYTE
  721.     JMP    PSH1        SAVE POINTER AND CONTINUE
  722. *
  723. * POPS A DOUBLE BYTE ENTRY FROM THE USER STACK
  724. *
  725. POPD    PUSH    H        SAVE H-L
  726.     LHLD    CSP        GET STACK POINTER
  727.     INX    H        ADVANCE TO LAST ENTRY
  728.     MOV    E,M        GET LOW BYTE
  729.     INX    H        ADVANCE TO HIGH BYTE
  730.     MOV    D,M        GET HIGH BYTE
  731.     JMP    PSH2        SAVE AND CONTINUE
  732. *
  733. * LET COMMAND, EVALUATE EXPRESSION
  734. *
  735. LET    CALL    EXPR        EVALUATE EXPRESSION
  736.     LDA    EFLAG        DID HE MAKE AN ASSIGNMENT?
  737.     ANA    A        IF NOT..
  738.     JZ    SYNT        HE'S MADE ANOTHER MISTAKE
  739.     SUB    A        RESET THE FLAG
  740.     STA    EFLAG        SO WE KNOW WHEN HE SCREW'S UP AGAIN
  741.     RET
  742. *
  743. * IT'S A NEXT COMMAND, TEST INDEX AGAINST LIMIT, AND LOOP IF NEEDED
  744. *
  745. NEXT    CALL    VCHAR        TEST FOR VALID VARIABLE
  746.     MOV    B,A        STASH IN B FOR SAFEKEEPING
  747.     LHLD    CSP        SAVE CONTROL STACK POINTER..
  748.     SHLD    TEMP        IN CASE WE NEED TO LOOP AGAIN
  749.     CALL    POPS        GET VARIABLE NAME FROM STACK
  750.     CMP    B        TEST FOR WHAT HE GAVE US
  751.     JNZ    NSTERR        IF NOT, HE'S SCREWED UP THE NESTING
  752.     CALL    LOOK        GET VARIABLE VALUE
  753.     PUSH    D        SAVE POSITION
  754.     CALL    POPD        GET LIMIT FROM STACK
  755.     MOV    B,D        GET LIMIT
  756.     MOV    C,E        INTO B-C SO WE CAN 'COMP'
  757.     CALL    COMP        TEST IF INDEX >= LIMIT
  758.     JNC    NOMORE        IF SO, DON'T LOOP ANYMORE
  759.     POP    D        GET POSITION BACK
  760.     INX    H        INCREMENT LOOP INDEX
  761.     LDAX    D        GET VARIABLE NAME BACK
  762.     CALL    STOR        SAVE IT AWAY
  763.     CALL    POPD        GET NEW POSITION
  764.     LHLD    TEMP        GET CONTROL-STACK POINTER
  765.     SHLD    CSP        AND REPLACE IT (LEAVING STACK UNCHANGED)
  766.     RET
  767. * WE HAVE HIT THE END OF A FOR NEXT LOOP
  768. NOMORE    CALL    POPD        CLEAN UP CONTROL STACK
  769.     POP    D        GET PROGRAM COUNTER BACK
  770. *
  771. * REMARK, DO NOTHING, BUT RETURN, ALLOWING 'RNEXT' TO SKIP THE COMMAND
  772. *
  773. REM    RET
  774. *
  775. * IT'S AN 'IF' STATEMENT. FIND OUT 'IF' WE DO IT OR NOT
  776. *
  777. IF    DCX    D        BACK UP IN SOURCE
  778.     MOV    A,E        GET LOW ADDRESS
  779.     STA    P        SAVE IN POSITION POINTER
  780. FTHEN    LDAX    D        GET CHARACTER FROM SOURCE
  781.     CPI    $0D        IF IT'S A CARRIAGE RETURN..
  782.     JZ    SYNT        THEN HE DIDN'T TYPE IN A 'THEN'
  783.     INX    D        ADVANCE TO NEXT CHARACTER
  784.     CPI    'T'        IS IT A 'T'?
  785.     JNZ    FTHEN        IF NOT, IT AINT THE START OF 'THEN'
  786.     LDAX    D        GET NEXT CHARACTER
  787.     CPI    'H'        TEST FOR NEXT CHARACTER OF 'THEN'
  788.     JNZ    FTHEN        NO, MUST BE VARIABLE 'T' (OR HE CAN'T SPELL)
  789.     DCX    D        BACK UP TO 'T'
  790.     PUSH    D        SAVE POSITION IN SOURCE
  791.     CALL    DOEXP        EVALUATE CONDITION EXPRESSION
  792.     POP    D        GET POSITION BACK
  793.     MOV    A,H        GET RESULT AND TEST.
  794.     ORA    L        IT FOR ZERO (FALSE)
  795.     RZ            IF SO, SKIP THIS STATEMENT
  796.     JMP    RLOOP        EXECUTE THE 'THEN'
  797. *
  798. * LONG IF, CONTROLS REMAINDER OF ENTIRE LINE
  799. *
  800. LIF    CALL    IF        CALCULATE AND PROCESS IF TRUE
  801. LNXT    INX    D        ADVANCE IN SOURCE
  802.     LDAX    D        GET CHARACTER FROM SOURCE
  803.     CPI    $0D        TEST FOR END OF LINE
  804.     JNZ    LNXT        KEEP LOOKING
  805.     RET
  806. *
  807. * IT A 'PLOT' COMMAND, (HE'S PLOTTING AGAINST US)
  808. *
  809. PLOT    CALL    EXPR        GET X COORDINATE
  810.     JC    SYNT        IF CHARACTER, IT'S NO GOOD
  811.     PUSH    H        SAVE X COORDINATE
  812.     INX    D        ADVANCE PAST ','
  813.     CALL    EXPR        GET Y COORDINATE
  814.     POP    B        GET X POSITION IN B-C
  815.     DAD    H        MULTIPLY.
  816.     DAD    H        Y POSITION.
  817.     DAD    H        BY 64.
  818.     DAD    H        TO PLACE ADDRESS.
  819.     DAD    H        ON PROPER LINE.
  820.     DAD    H        OF THE DISPLAY
  821.     DAD    B        ADD IN X POSITION
  822.     LXI    B,1024        TEST AGAINST END OF SCREEN
  823.     CALL    COMP        TO SEE IF WE ARE OVER
  824.     JNC    DIMERR        IF SO, 'DIMENSION ERROR'
  825.     CALL    CURPOS        POSITION THE CURSOR
  826. * LOOK FOR END OF LINE, OR OTHER OPERANDS
  827.     CALL    SKIP        GET NEXT SEPERATOR
  828.     CPI    ','        TEST FOR COMMA
  829.     RNZ            IF NOT, WE ARE DONE
  830.     INX    D        SKIP ','
  831. *
  832. * PRINT STATEMENT, LET'S OUTPUT SOMETHING SO HE WON'T GET UPSET
  833. * WHILE STAREING AT THE TUBE WONDERING IF WE DIED
  834. *
  835. PRINT    CALL    EXPR        GET EXPRESSION TO PRINT
  836.     PUSH    D        SAVE BASIC'S PROGRAM COUNTER
  837.     CNC    DECPRT        IF NUMERIC, OUTPUT DECIMAL NUMBER
  838.     POP    D        RESTORE BASIC'S PROGRAM COUNTER
  839.     CC    PV1        IF CHARACTER, DISPLAY CHARACTER VALUE
  840.     LDAX    D        GET CHARACTER FROM SOURCE
  841.     CPI    ','        TEST FOR COMMA
  842.     JNZ    NL        IF NOT, IT'S THE END
  843.     CALL    PARSE        ADVANCE TO NEXT NON-BLANK
  844.     JNZ    PRINT        PRINT NEXT EXPRESSION
  845.     RET
  846. * PRINT CHARACTER EXPRESSIONS
  847. PV1    LXI    H,XBF        EXPRESSION IS IN EXTRA BUFFER
  848. PZ    MOV    A,M        GET CHARACTER FROM EXPRESSION
  849.     INX    H        POINT TO NEXT
  850.     ANA    A        TEST FOR END OF EXPRESSION
  851.     RM            IF SO, END IT NOW
  852.     CALL    OUT        PRINT CHARACTER
  853.     JMP    PZ        KEEP GOING TILL END
  854. * RECURSIVE ROUTINE OUTPUTS NUMBER IN DECIMAL
  855. DECPRT    CPI    '('        TEST FOR SPECIAL CASE
  856.     CNZ    SPACE        IF NOT, PRECEDE WITH SPACE
  857. DECP1    LXI    B,10        DIVIDE BY 10
  858.     CALL    DODIV        PERFORM DIVISION
  859.     MVI    A,$30        TO CONVERT TO ASCII
  860.     ADD    L        GET DIGIT
  861.     PUSH    PSW        SAVE FOR OUTPUT
  862.     XCHG            SWAP, REMAINDER IS NOW IN HL
  863.     MOV    A,H        GET HIGH BYTE
  864.     ORA    L        TEST FOR ZERO, (FINISHED)
  865.     CNZ    DECP1        IF NOT, GET NEXT VALUE
  866.     POP    PSW        GET DIGIT OFF STACK
  867.     JMP    OUT        DISPLAY AND RETURN
  868. *
  869. * IT'S AN 'INPUT', LETS GIVE HIM A CHANCE TO DO SOME TYPING.. BUT
  870. * KEEP AN EYE ON HIM, IN CASE HE TRY'S TO PUT SOMETHING OVER ON US
  871. *
  872. INPUT    CALL    CLBF        CLEAR EXTRA TEXT BUFFER
  873.     MVI    A,'?'        GET A QUESTION MARK.
  874.     STA    XBF        TO USE AS THE DEFAULT PROMPT
  875.     LDAX    D        GET FIRST CHAR OF OPERAND
  876.     CPI    $22        TEST FOR USER SUPPLIED PROMPT
  877.     JNZ    INP1        IF NOT, DON'T CHANGE EXISTING ONE
  878.     CALL    EXPR        EVALUATE USER SUPPLIED PROMPT
  879.     CALL    PARSE        SKIP TO NEXT NON-BLANK
  880. INP1    CALL    VCHAR        TEST FOR VALID VARIABLE NAME
  881.     PUSH    D        SAVE SOURCE POSITION
  882.     INX    D        ADVANCE TO NEXT CHARACTER
  883.     PUSH    PSW        SAVE VARIABLE NAME
  884.     LDAX    D        GET NEXT CHARACTER
  885.     CPI    '$'        TEST FOR CHARACTER INPUT
  886.     JZ    GCHR        IF SO, GET CHARACTER DATA
  887.     LXI    H,0        START WITH A ZERO
  888.     DAD    SP        AND GET STACK POINTER. IN CASE WE BLOW UP
  889.     SHLD    TEMP        SAVE SO WE CAN GET IT BACK LATER
  890. RETRY    CALL    PV1        DISPLAY USER PROMPT
  891.     SUB    A        GET A ZERO
  892.     STA    IFLAG        AND CLEAR THE INPUT FLAG (IN CASE HE CTRL-C'S)
  893.     CALL    GLINE        GET A LINE FROM THE TERMINAL
  894.     STA    IFLAG        SET IFLAG. (SO GET ERROR, WE CAN COME BACK)
  895.     CALL    EXPR        EVALUATE EXPRESSION
  896.     POP    PSW        RESTORE VARAIABLE NAME
  897.     CALL    STOR        STASH VALUE IN VARIABLE
  898.     POP    D        RESTORE SOURCE POSITION
  899.     SUB    A        GET A ZERO
  900.     STA    IFLAG        AND CLEAR IFLAG
  901.     RET
  902. * CHARACTER INPUT
  903. GCHR    CALL    PV1        DISPLAY USER PROMPT
  904.     CALL    GLINE        GET A LINE OF INPUT
  905.     POP    PSW        GET VARIABLE BACK
  906.     CALL    LTA        GET THE TEXT VARIABLE'S ADDRESS
  907.     MVI    B,35        LENGTH IS 35
  908. Z1    LDAX    D        GET CHARACTER FROM INPUT BUFFER
  909.     CPI    $0D        TEST FOR END OF BUFFER
  910.     JZ    Z2        IF SO, END THE LINE
  911.     DCR    B        TEST FOR END OF VARIABLE SPACE
  912.     JZ    Z2        IF SO, END THE LINE
  913.     MOV    M,A        SAVE IN VARIABLE SPACE
  914.     INX    H        NEXT CHARACTER IN VARIABLE
  915.     INX    D        NEXT CHARACTER IN INPUT BUFFER
  916.     JMP    Z1        COPY NEXT CHARACTER
  917. Z2    POP    D        RESTORE SOURCE POSITION
  918. Z3    MVI    M,$FF        PAD BUFFER WITH NULL CHARACTERS
  919.     INX    H        NEXT POSITION IN VARIABLE
  920.     DCR    B        REDUCE COUNT TILL END
  921.     JP    Z3        KEEP GOING TILL VARIABLE IS FILLED
  922.     RET
  923. *
  924. * LOOK'S LIKE HE CAN'T EVEN ENTER A SIMPLE NUMBER, CLEAN UP ANY STACK
  925. * HE MAY HAVE USED, AND LET HIM TAKE ANOTHER BLIND STAB AT THE KEYBOARD
  926. *
  927. INERR    LXI    H,IERMS        GET NASTY MESSAGE
  928.     CALL    PMSG        GIVE HIM THE BAD NEWS
  929.     LHLD    TEMP        GET HIS OLD STACK BACK
  930.     SPHL            RESET HIS STACK
  931.     JMP    RETRY        LET HIM TRY AGAIN
  932. *
  933. * DIMENSION, HE WANTS SOME ARRAY SPACE.. I SUPPOSE WE SHOULD GIVE IT TO HIM
  934. *
  935. DIM    MOV    A,E        GET ADDRESS OF OUR POSITION
  936.     STA    P        SAVE IN POSITION POINTER
  937. DIM0    LDAX    D        GET CHARACTER FROM SOURCE
  938.     INX    D        ADVANCE TO NEXT
  939.     CPI    $0D        TEST FOR END OF LINE
  940.     JZ    SYNT        IF SO, TELL HIM TO STRAIGHTEN UP
  941.     CPI    ')'        TEST FOR START OF ARRAY DIMENSION
  942.     JNZ    DIM0        IF NOT, KEEP LOOKING
  943.     DCX    D        BACK UP FOR EXPRESSION
  944.     PUSH    D        SAVE BASIC PROGRAM COUNTER
  945.     CALL    DOEXP        EVALUATE ARRAY SIZE
  946.     INX    H        ADD ONE ENTRY (ZERO ENTRY DOES EXIST)
  947.     DAD    H        DOUBLE BECAUSE THEY ARE 16 BIT'S
  948.     DCX    D        BACK UP TO NAME
  949.     MOV    B,H        COPY SIZE NEEDED
  950.     MOV    C,L        INTO B AND C
  951.     LHLD    LAST        GET FREE ADDRESS
  952.     PUSH    H        SAVE FOR TABLE
  953. DLOOP    MVI    M,0        ZERO ARRAY BYTE
  954.     INX    H        ADVANCE TO NEXT
  955.     DCX    B        REDUCE COUNT
  956.     MOV    A,B        GET HIGH BYTE OF REMAINING TO DO
  957.     ORA    C        TEST FOR NONE LEFT
  958.     JNZ    DLOOP        IF NOT, KEEP ZEROING
  959.     SHLD    LAST        SAVE NEXT FREE SPACE INDICATOR
  960.     POP    H        GET ADDRESS OF ARRAY BACK
  961.     LDAX    D        GET ARRAY NAME
  962.     CALL    TABENT        GET TABLE ENTRY
  963.     MOV    A,H        GET HIGH ADDRESS
  964.     STAX    B        PLACE IN TABLE
  965.     INX    B        ADVANCE IN TABLE
  966.     MOV    A,L        GET LOW ADDRESS
  967.     STAX    B        PLACE IN TABLE
  968.     POP    D        GET SOURCE POSITION BACK
  969.     CALL    PARSE        ADVANCE TO NEXT NON-BLANK
  970.     RZ
  971.     CPI    ','        TEST FOR ANOTHER OPERAND
  972.     JZ    DIM        IF SO, KEEP GOING
  973.     SUB    A        CAUSE A SYNTAX ERROR BECAUSE WE ARE BAD
  974. *
  975. * LOCATES TABLE POSITION OF AN ARRAY
  976. *
  977. TABENT    CALL    VCHAR        INSURE IT'S OK
  978.     SUI    'A'        CONVERT TO BINARY
  979.     ADD    A        X 2 FOR TWO BYTE ENTRIES
  980.     MOV    C,A        SAVE IN C
  981.     LDA    ARYLOC        GET ARRAY PAGE
  982.     MOV    B,A        SAVE IN HIGH ZBYTE
  983.     RET
  984. * LOOKS UP AN ARRAY VALUE
  985. ALOOK    CALL    DOEXP        CALCULATE INDEX VALUE
  986.     DCX    D        BACK UP PAST '['
  987.     LDAX    D        GET VARIABLE NAME
  988.     CALL    LOOKT        FIND ADDRESS OF ENTRY
  989.     MOV    B,M        GET HIGH BYTE OF ENTRY
  990.     INX    H        ADVANCE TO LOW BYTE
  991.     MOV    C,M        GET LOW BYTE OF ARRAY ENTRY
  992.     MOV    H,B        TRANSFER RESULT TO .
  993.     MOV    L,C        H AND L WHERE THEY ARE EXPECTED
  994.     LDAX    D        GET VARIABLE NAME BACK
  995.     CPI    '@'        TEST FOR MAGIC 'PEEK' ARRAY
  996.     RNZ            IF NOT, WE ARE OK
  997.     MOV    L,H        SET VALUE TO THAT OF FIRST BYTE
  998.     MVI    H,0        AND ELIMINATE HIGH BYTE
  999.     RET
  1000. *
  1001. * LOCATES ADDRESS OF AN ARRAY ENTRY IN THE ARRAY TABLE. INDEX IN HL
  1002. *
  1003. LOOKT    CPI    '@'        TEST FOR SPECIAL CASE
  1004.     RZ            IF SO, PEEK AT ADDRESS
  1005.     CALL    TABENT        LOCATE TABLE ENTRY
  1006.     PUSH    D        SAVE BASIC PROGRAM COUNTER
  1007.     LDAX    B        GET FIRST BYTE
  1008.     MOV    D,A        COPY TO HIGH BYTE
  1009.     INX    B        ADVANCE TO NEXT
  1010.     LDAX    B        GET LOW BYTE
  1011.     MOV    E,A        COPY TO D
  1012.     DAD    H        X TWO FOR TWO BYTE ENTRIES
  1013.     DAD    D        ADD IN OFFSET FOR START OF ARRAY
  1014.     ORA    D        TEST FOR ADDRESS OF ZERO, = NOT DIMENSIONED
  1015.     POP    D        RESTORE PROGRAM COUNTER
  1016.     RNZ            NOT A DIMENSION ERROR, GO BACK
  1017. *
  1018. * EITHER HE'S TRIED TO INDEX A NON-ARRAY VARIABLE, TRIED TO INDEX A CHARACTER
  1019. * VARIABLE WITH A VALUE GREATER THEN 34, OR HE'S PLOTTED OUTSIDE OF THE SCREEN
  1020. * NO MATTER WHAT HE'S DONE, GIVE HIM A NASTY MESSAGE SO HE WON'T DO IT AGAIN
  1021. *
  1022. DIMERR    LXI    H,OVM        ADDRESS OF NASTY MESSAGE
  1023.     JMP    ERR        GIVE IT TO HIM
  1024. * LOCATES THE ADDRESS OF A CHARACTER (TEXT) VARIABLE
  1025. LTA    SUI    $41        REDUCE TO SIMPLE BINARY
  1026.     CPI    26        TEST FOR VALID VARIABLE
  1027.     JNC    SYNT        IF NOT, GET MAD
  1028.     LXI    H,VARS+25    START OF CHARACTER VARIABLES (-37)
  1029.     LXI    B,37        LENGTH OF CHARACTER VARIABLES
  1030. V1    DAD    B        OFFSET INTO TABLE
  1031.     DCR    A        REDUCE VARIABLES WE HAVE TO GO
  1032.     JP    V1        IF NOT FINISHED, KEEP OFFSETING
  1033.     RET
  1034. *
  1035. * IT'S A 'USR' COMMAND, FIND OUT WHAT HE WANT'S, PASS CONTROL  TO
  1036. * HIS MACHINE LANGUAGE ROUTINE, AND GOD HELP HIM IF HE SCREW'S UP
  1037. * BECAUSE WE CAN'T DO ANYTHING FOR HIM UNTIL HE RETURNS
  1038. *
  1039. USR    LXI    H,URET        GET ON STACK (SO HE CAN 'RET' TO IT)
  1040.     PUSH    H        SAVE IN MACHINE STACK
  1041.     CALL    EXPR        EVALUATE ADDRESS
  1042.     PUSH    H        SAVE ON STACK (SO WE CAN 'RET' TO IT)
  1043.     LDAX    D        GET NEXT CHARACTER
  1044.     CPI    ','        TEST FOR MORE PARAMETERS
  1045.     JNZ    CSAV        IF NOT, DONT EVALUATE
  1046.     INX    D        SKIP THE ','
  1047.     CALL    EXPR        EVALUATE PARAMETER TO PASS
  1048. * WHEN 'PUSHD' RETURNS, IT WILL EFFECT A JUMP TO HIS CODE
  1049. CSAV    JMP    PUSHD        SAVE PROGRAM POSITION
  1050. * IF WE GET HERE, HE MADE IT BACK IN ONE PIECE
  1051. URET    CALL    POPD        GET PROGRAM COUNTER BACK
  1052.     LDAX    D        GET CHARACTER FROM SOURCE
  1053.     CPI    ','        TEST FOR VARIABLE TO RECEIVE H-L
  1054.     RNZ            IF NOT, WE ARE DONE
  1055.     CALL    PARSE        KEEP LOOKING
  1056. *
  1057. * STORES H-L INTO A INTEGER VARIABLE PASSED IN A
  1058. *
  1059. STOR    MVI    B,=VARS        GET ADDRESS OF VARIABLE TABLE
  1060.     SUI    $41        CONVERT TO BINARY
  1061.     CPI    26        TEST FOR VALID VARIABLE NAME
  1062.     JNC    SYNT        IF NOT, IT'S INVALID
  1063.     ADD    A        DOUBLE BECAUSE THEY ARE 16 BIT ENTRIES
  1064.     MOV    C,A        PLACE IN C, MAKING COMPLETE ADDRESS
  1065.     MOV    A,L        GET HIGH VALUE TO SAVE
  1066.     STAX    B        SAVE IN VARIABLE
  1067.     INX    B        NEXT BYTE OF VARIABLE
  1068.     MOV    A,H        GET LOW BYTE
  1069.     STAX    B        SAVE IN VARIABLE
  1070.     RET
  1071. *
  1072. * RETERIVES CONTENTS OF A VARIABLE
  1073. *
  1074. LOOK    MVI    B,=VARS        ADDRESS OF VARIABLES
  1075.     SUI    $41        CONVERT NAME TO BINARY
  1076.     ADD    A        DOUBLE FOR 16 BIT ENTRIES
  1077.     MOV    C,A        MAKE COMPLETE ADDRESS
  1078.     LDAX    B        GET HIGH BYTE
  1079.     MOV    L,A        PLACE IN H
  1080.     INX    B        NEXT BYTE OF VARIABLE
  1081.     LDAX    B        GET LOW BYTE
  1082.     MOV    H,A        PLACE IN L
  1083.     RET
  1084. *
  1085. * IT'S AN 'ORDER', (HE THINKS HE KNOWS WHERE THERE IS SOME DATA)
  1086. *
  1087. ORDER    PUSH    D        SAVE OUR SOURCE POSITION
  1088.     CALL    FNDLIN        GET ADDRESS OF THE LINE HE WANTS
  1089.     POP    D        RESTORE OUR POSITION
  1090.     PUSH    D        AND RESAVE OUR POSITION
  1091.     JNZ    BADLIN        IF IT DOSN'T EXIST, THEN FORGET IT
  1092.     INX    H        SKIP FIRST TWO DIGITS OF LINE NUMBER
  1093.     INX    H        SKIP LAST TWO DIGITS OF LINE NUMBER
  1094.     INX    H        SKIP LENGTH BYTE
  1095.     XCHG            MOVE TO D-E
  1096.     CALL    VERDAT        GET STATEMENT FROM LINE
  1097.     SHLD    DATA        SAVE DATA POINTER
  1098.     POP    D        RESTORE OUR LINE, (SO WE CAN TELL HIM)
  1099.     RZ
  1100. *
  1101. * DATA ERROR... ATTEMPT TO READ FROM A LINE WITHOUT 'DATA' OR
  1102. * ATTEMPT TO READ THE WRONG DATA TYPE. LET HIM IN ON IT
  1103. *
  1104. DERR    LXI    H,DTXT        ADDRESS OF 'DATA' MESSAGE
  1105.     JMP    SYNT+3        DISPLAY IT
  1106. *
  1107. * IT'S A READ. (HE WANTS TO KNOW WHATS IN THAT DATA WE FOUND)
  1108. *
  1109. READ    CALL    VCHAR        IS IT A VALID VARIABLE
  1110.     PUSH    PSW        SAVE VARIABLE NAME
  1111.     INX    D        ADVANCE TO NEXT CHARACTER
  1112.     LDAX    D        GET NEXT CHARACTER
  1113.     CPI    '$'        IS IT A CHARACTER VARIABLE?
  1114.     JZ    CDAT        IF SO, LOOK FOR CHARACTER DATA
  1115. * NUMERIC DATA, FOR NUMERIC VARIABLE
  1116.     CALL    GETDAT        GET NUMERIC DATA
  1117.     JC    DERR        IF CHARACTER, IT A DATA TYPE ERROR
  1118.     POP    PSW        GET VARIABLE NAME BACK
  1119.     CALL    STOR        STASH VALUE IN IT
  1120.     JMP    MORDAT        SEE IF HE WANT'S MORE DATA
  1121. * CHARACTER DATA, FOR CHARACTER VARIABLE
  1122. CDAT    INX    D        SKIP DOLLAR SIGN
  1123.     CALL    GETDAT        GET DATA
  1124.     JNC    DERR        IF NUMERIC, IT'S BAD
  1125.     POP    PSW        GET VARIABLE NAME BACK
  1126.     CALL    LTA        FIND IT'S ADDRESS
  1127.     LXI    B,XBF        DATA IS IN EXTRA BUFFER
  1128.     PUSH    D        SAVE SOURCE POSITION
  1129.     MVI    E,35        MOVE 35 CHARACTERS
  1130. SL1    LDAX    B        GET CHARACTER FROM BUFFER. (DATA)
  1131.     MOV    M,A        STASH IT IN THE VARIABLE
  1132.     INX    B        SKIP TO THE NEXT CHARACTER IN THE BUFFER
  1133.     INX    H        SKIP TO THE NEXT POSITION IN VARIABLE
  1134.     DCR    E        REDUCE COUNT OF HOW MANY TO MOVE
  1135.     JNZ    SL1        IF NOT FINISHED, KEEP COPYING
  1136.     POP    D        RESTORE SOURCE POSITION
  1137. * LOOK FOR MORE VARIABLES (OPERANDS) IN THE 'READ' STATEMENT
  1138. MORDAT    CALL    PARSE1        FIND NEXT NON-BLANK
  1139.     CPI    ','        IF COMMA..
  1140.     RNZ            IF NOT, WE HAVE ALL THERE IS
  1141.     CALL    PARSE        SKIP COMMA AND FIND VARIABLE NAME
  1142.     JMP    READ        GET MORE DATA FOR FOLLOWING VARIABLE
  1143. * GETS DATA FROM THE DATA STATEMENTS, POINTED TO BY THE CURRENT READ POINTER
  1144. GETDAT    LHLD    DATA        GET DATA POINTER
  1145.     MOV    A,H        SEE IF IT IS ZERO.
  1146.     ORA    L        WHICH INDICATES THAT IT WASN'T INITIALIZED
  1147.     JZ    DERR        IF SO, IT'S A DATA ERROR
  1148.     PUSH    D        SAVE SOURCE POSIITION
  1149.     XCHG            SWAP DATA POINTER TO D-E
  1150.     CALL    EXPR        EVALUATE THE DATA EXPRESSION
  1151.     PUSH    PSW        SAVE THE CONDITION FLAGS
  1152. ENDAT    LDAX    D        GET NEXT CHARACTER FROM THE SOURCE
  1153.     CPI    ','        TEST FOR MORE DATA
  1154.     JZ    COMA        IF SO, WE ARE OK
  1155.     CPI    ':'        TEST FOR END OF STATEMENT
  1156.     JZ    DAT1        GO TO NEXT DATA STATEMENT
  1157.     INX    D        ADVANCE ONE CHARACTER
  1158.     CPI    $0D        CARRIAGE RETURN?
  1159.     JNZ    ENDAT        KEEP LOOKING IF NOT
  1160. * HIT THE END OF A LINE, SKIP TO NEXT DATA STATEMENT
  1161.     INX    D        SKIP FIRST TWO DIGITS
  1162.     INX    D        SKIP SECOND TWO DIGITS
  1163. DAT1    INX    D        SKIP LENGTH (OR ':' IF STMT)
  1164.     PUSH    H        SAVE H-L REG
  1165.     CALL    VERDAT        CHECK FOR DATA STATEMENT
  1166.     XCHG            SWAP POINTER BACK TO D-E
  1167.     POP    H        RESTORE REGISTERS
  1168.     JZ    GDEND        RETURN, WITH NEW DATA POINTER
  1169.     LXI    D,$FFFF        INDICATE NO MORE DATA STATEMENTS
  1170. COMA    INX    D        SKIP THE COMMA
  1171. GDEND    XCHG            SWAP DATA POINTER BACK TO H-L
  1172.     SHLD    DATA        SAVE IN POINTER
  1173.     XCHG            SWAP VALUE BACK TO H-L
  1174.     POP    PSW        GET FLAGS BACK
  1175.     POP    D        GET SOURCE POSITION BACK
  1176.     RET
  1177. *
  1178. * VERIFY THAT COMMAND WAS 'DATA'
  1179. *
  1180. VERDAT    CALL    PARSE1        SKIP TO COMMAND
  1181.     XCHG            SWAP TO H-L
  1182.     LXI    D,DATCMD    POINT TO DATA COMMAND
  1183. VER1    MOV    A,E        GET LOW ADDRESS
  1184.     CPI    DATCMD+4    ARE WE AT END
  1185.     RZ
  1186.     LDAX    D        GET CHR FROM TABLE
  1187.     INX    D        ADVANCE TO NEXT
  1188.     ANI    $7F        INSURE IT'S CORRECT
  1189.     CMP    M        DUZ IT MATCH?
  1190.     INX    H        NEXT IN DATA COMMAND
  1191.     JZ    VER1        OK, TEST NEXT
  1192.     RET
  1193. *
  1194. * HE WANT'S TO KNOW HOW BIG IT IS... LETS FIGURE IT OUT AND LET HIM IN ON IT
  1195. *
  1196. SIZE    PUSH    D        SAVE PROGRAM POINTER
  1197.     CALL    GETEOF        FIND THE END OF THE FILE
  1198.     LXI    B,0-TEXT    GET THE (NEGATIVE) FILE START ADDRESS
  1199.     DAD    B        SUBTRACT FILE START FROM FILE END
  1200.     CALL    DECPRT        DISPLAY VALUE IN DECIMAL
  1201.     LXI    H,SIMSG        GET ' BYTES' MESSAGE
  1202.     POP    D        RESTORE PROGRAM POINTER
  1203.     JMP    PMSG        TELL HIM WHAT IT IS
  1204. * FINDS THE END OF THE FILE, HL=LAST BYTE OF PGM., A=FIRST FREE PAGE
  1205. GETEOF    LXI    H,TEXT        START AT THE BEGINING
  1206.     MVI    A,255        LOOKING FOR AN FF
  1207. GLPX    CMP    M        IS THIS IT?
  1208.     INX    H        ADVANCE TO NEXT
  1209.     JNZ    GLPX        IF NOT IT, KEEP LOOKING
  1210.     DCX    H        POINT BACK TO $FF
  1211.     MOV    A,H        GET HIGH VALUE
  1212.     INR    A        ADVANCE TO NEXT PAGE
  1213.     RET
  1214. *
  1215. * HE'S TRYING TO 'LOAD' SOMETHING, I WONDER IF HE HAS SOMETHING SAVED..
  1216. *
  1217. LOAD    CALL    TON        TURN ON TAPE AND WAIT
  1218. LOD1    CALL    GETR        GET A RECORD
  1219.     JC    LOD1        KEEP GOING TILL WE HAVE IT ALL
  1220.     CALL    TOFF        SHUT TAPE OFF
  1221.     JMP    RESV        CLEAR VARIABLES AND GET A NEW COMMAND
  1222. *
  1223. * HE'S TRYING TO 'SAVE' SOMETHING..
  1224. *
  1225. SAVE    PUSH    D        SAVE PROGRAM POINTER
  1226.     LXI    D,TEXT        GET ADDRESS OF TEXT
  1227.     LDAX    D        GET FIRST BYTE
  1228.     INR    A        TEST FOR NO PROGRAM
  1229.     JZ    RUN        IF SO, RUN WILL ABORT WITH ERROR
  1230.     CALL    GETEOF        GET ENDING ADDRESS
  1231.     CALL    TDUMP        DUMP PROGRAM AND RETURN
  1232.     POP    D        RESTORE PROGRAM POINTER
  1233.     RET
  1234. *
  1235. *****************************************************************
  1236. *                 EXPRESSION EVALUATION CODE
  1237. *****************************************************************
  1238. *
  1239. * EVALUATES 16 BIT DECIMAL NUMBERS
  1240. *
  1241. EVAL    LXI    B,1        MULTIPLIER IS ONE
  1242.     MOV    H,B        INITIALIZE
  1243.     MOV    L,B        STARTING RESULT TO ZERO
  1244. ETOP    LDAX    D        GET DIGIT FROM SOURCE
  1245.     CALL    NUM        TEST FOR INVALID DIGIT
  1246.     RC            IF SO, WE ARE FINISHED
  1247.     ANI    $0F        CONVERT TO BINARY
  1248. * ADD DIGIT TIMES MULTIPLIER IN B-C TO H-L
  1249. ZLOOP    DCR    A        REDUCE BY ONE
  1250.     JM    ESP1        EXIT WHEN EXAUSTED
  1251.     DAD    B        ADD MULTIPLIER
  1252.     JMP    ZLOOP        CONTINUE TILL DONE
  1253. * MULTIPLY MULTIPLIER (BC) BY 10
  1254. ESP1    PUSH    H        SAVE H-L
  1255.     MOV    H,B        GET B-C INTO
  1256.     MOV    L,C        H-L SO WE CAN USE 'DAD'
  1257.     DAD    B        BC=BC*2
  1258.     DAD    H        BC=BC*4
  1259.     DAD    B        BC=BC*5
  1260.     DAD    H        BC=BC*10
  1261.     MOV    B,H        SAVE BACK INTO
  1262.     MOV    C,L        B-C REGISTER PAIR
  1263.     POP    H        RESTORE H-L
  1264.     DCX    D        REDUCE POINTER IN SOURCE
  1265.     JMP    ETOP        EVALUATE NEXT CHARACTER
  1266. *
  1267. * SUBROUTINE TESTS FOR VALID ASCII CHARACTERS
  1268. *
  1269. CHAR    CPI    'A'        TEST FOR < 'A'
  1270.     RC            RETURN SAYING IT'S BAD
  1271.     CPI    '['        TEST FOR >'Z'
  1272.     CMC            INVERT LOGIC
  1273.     RET
  1274. *
  1275. * PARSES FORWARD, SEARCHING FOR FIRST NON-BLANK CHARACTER
  1276. *
  1277. PARSE    INX    D        ADVANCE IN SOURCE
  1278. PARSE1    LDAX    D        GET CHARACTER FROM SOURCE
  1279.     CPI    ' '        TEST FOR SPACE
  1280.     JZ    PARSE        KEEP LOOKING
  1281.     CPI    ':'        TEST FOR END OF STATEMENT
  1282.     RZ            IF SO, RETURN WITH Z SET
  1283.     CPI    $0D        TEST FOR END OF LINE
  1284.     RET
  1285. *
  1286. * SKIPS TO NEXT EXPRESSION OR COMMAND
  1287. *
  1288. SKIP    CALL    PARSE1        ADVANCE TO NEXT NON-BLANK
  1289.     DCX    D        BACK UP TO POSITION
  1290.     MOV    A,E        GET LOW ORDER ADDRESS
  1291.     STA    P        SAVE IN POSITION BYTE
  1292. * LOOK FOR DELIMITER
  1293. SKIP1    INX    D        ADVANCE TO NEXT
  1294.     LDAX    D        GET CHARACTER
  1295.     CPI    ':'        TEST FOR DELIMITER
  1296.     RZ            IF SO, RETURN
  1297.     CPI    ','        TEST FOR DELIMITER
  1298.     RZ            IF SO, RETURN
  1299.     CPI    $0D        TEST FOR DELIMITER
  1300.     RZ            IF SO, RETURN
  1301.     CPI    $22        TEST FOR QUOTE
  1302.     CZ    SKPQUO        IF SO, ADVANCE TO NEXT QUOTE
  1303.     JMP    SKIP1        KEEP LOOKING
  1304. * FIND NEXT QUOTE IN SOURCE
  1305. SKPQUO    INX    D        ADVANCE TO NEXT CHARACTER IN SOURCE
  1306.     LDAX    D        GET THE CHARACTER
  1307.     CPI    $22        IS IT A QUOTE?
  1308.     RZ            IF SO, WE FOUND IT
  1309.     CPI    $0D        IF IT A CARRIAGE RETUEN
  1310.     JNZ    SKPQUO        IF NOT, OK
  1311.     JMP    SYNT        UNMATCHED QUOTES WHILE PARSING
  1312. *
  1313. * EVALUATES AN EXPRESSION POINTED TO BY D-E. RETURN WITH CARRY SET
  1314. * INDICATES THAT EXPRESSION WAS A CHARACTER EXPRESSION
  1315. *
  1316. EXPR    CALL    SKIP        ADVANCE TO END OF EXPRESSION
  1317.     PUSH    D        SAVE POINTER TO END
  1318.     CALL    DOEXP        EVALUATE
  1319.     POP    D        RESTORE POINTER TO END OF EXPRESSION
  1320.     RET
  1321. * CALCULATES EXPRESSION BACKWARDS (LIKE APL)
  1322. DOEXP    DCX    D        BACK UP IN SOURCE
  1323.     CALL    FE        GET CHARACTER FROM SOURCE
  1324.     CPI    '$'        TEST FOR CHARACTER VARIABLE
  1325.     JZ    CEXP        IF SO, ITS A CHARACTER EXPRESSION
  1326.     CPI    $22        TEST FOR QUOTE
  1327.     JZ    CEXP        IF SO, IT'S A CHARACTER EXRESSION
  1328.     INX    D        ADVANCE
  1329.     MVI    A,';'        NULL OPERATOR TO START
  1330. EGO1    PUSH    H        SAVE OLD VALUE
  1331.     PUSH    PSW        SAVE OPERATOR
  1332.     DCX    D        BACK UP TO VALUE
  1333.     CALL    FE        GET CHARACTER FROM SOURCE
  1334.     CPI    ')'        TEST FOR BRACKET
  1335.     JZ    BRKTS        IF SO, RECURSE
  1336.     CPI    ']'        TEST FOR ARRAY LOOKUP
  1337.     JZ    ARYL        IF SO, LOOK UP ARRAY VALUE
  1338.     CALL    CHAR        TEST FOR VARAIABLE
  1339.     JNC    LOOKU        IF SO, LOOK IT UP
  1340.     CPI    '?'        TEST FOR RANDOM NUMBER RETERIVAL
  1341.     JZ    RANDR        GET RANDOM VALUE
  1342.     CPI    '#'        TEST FOR HEX CONSTANT
  1343.     JZ    HEXVL        IF SO, GET HEV VALUE
  1344.     CALL    NUM        TEST FOR A NUMBER
  1345.     JC    SYNT        IF NOT, I DON'T KNOW WHAT HE'S DOING
  1346. * DECIMAL NUMBER
  1347. CALN    CALL    EVAL        EVALUATE DECIMAL NUMBER
  1348.     JMP    OLOOK        LOOK FOR OPERATOR
  1349. * HEX. NUMBER
  1350. HEXVL    DCX    D        BACK UP IN SOURCE
  1351.     LDA    P        GET ENDING POSITION
  1352.     CMP    E        TEST FOR PASSED THE LIMIT
  1353.     JZ    HEXGO        IF SO, THATS IT
  1354.     LDAX    D        GET CHARACTER FROM SOURCE
  1355.     CALL    NUM        TEST FOR VALID DIGIT
  1356.     JNC    HEXVL        KEEP GOING TILL WE GET TO START OF STRING
  1357.     SUI    'A'        TEST FOR VALID LETTER
  1358.     CPI    6        OF 'A' TO 'F'
  1359.     JC    HEXVL        IF SO, KEEP LOOKING
  1360. HEXGO    LXI    H,0        START WITH A ZERO
  1361.     MOV    B,H        FLAG TO SEE IF ANY DIGITS
  1362.     PUSH    D        SAVE POSITION IN SOURCE
  1363. GETHX    INX    D        ADVANCE TO NEXT DIGIT OF HEX NUMBER
  1364.     LDAX    D        GET DIGIT
  1365.     CPI    '#'        TEST FOR END OF STRING
  1366.     JZ    HGON        IF SO, WE ARE DONE
  1367.     MOV    B,A        SET FLAG SO WE KNOW WE GOT AT LEAST ONE DIGIT
  1368.     DAD    H        SHIFT H-L
  1369.     DAD    H        RIGHT IN ORDER
  1370.     DAD    H        TO MAKE ROOM FOR
  1371.     DAD    H        THE NEW DIGIT
  1372.     SUI    '0'        REDUCE TO BINARY
  1373.     CPI    10        TEST FOR FURTHER REDUCTION NEEDED
  1374.     JC    HISG        IF NOT, PROCESS
  1375.     SUI    7        CONVERT LETTER TO BINARY
  1376. HISG    ORA    L        ADD IN BOTTOM DIGIT OF RESULT
  1377.     MOV    L,A        REPLACE IN RESULT
  1378.     JMP    GETHX        GET NEXT DIGIT
  1379. HGON    POP    D        GET POSITION IN SOURCE BACK
  1380.     MOV    A,B        GET FLAG
  1381.     ANA    A        TEST FOR DIGIT'S PROCESSED
  1382.     JNZ    OLOOK        NO PROBLEM
  1383.     JMP    SYNT        '#' WITH NO DIGITS... ERROR
  1384. * A ')' HAS BEEN DETECTED
  1385. BRKTS    CALL    DOEXP        RECURSE ON OURSELVES
  1386.     JMP    DCLB        CONTINUE WITH VALUE
  1387. * LOOK UP AN ARRAY VALUE
  1388. ARYL    POP    PSW        GET OPERATOR BACK
  1389.     PUSH    PSW        STASH OPERATOR
  1390.     CPI    '='        TEST FOR ASSIGNMENT
  1391.     CNZ    ALOOK        IF NOT, GET VALUE
  1392.     JMP    DCLB        CONTINUE WITH VALUE
  1393. * GET VARIABLE CONTENTS
  1394. LOOKU    CALL    LOOK        LOOK UP VALUE OF VARIABLE
  1395. DCLB    DCX    D        BACK UP IN SOURCE
  1396. OLOOK    POP    PSW        GET OPERATOR BACK
  1397.     POP    B        GET OLD VALUE BACK
  1398. * 16 BIT ADDITION
  1399.     CPI    '+'        TEST FOR ADDITION
  1400.     JZ    ADD        IF SO, PERFORM ADD
  1401. * SIXTEEN BIT SUBTRACTION
  1402.     CPI    '-'        TEST FOR SUBTRACTION
  1403.     JNZ    MULT        NO, TRY MULTIPLICATION
  1404.     MOV    A,B        GET B
  1405.     CMA            COMPLEMENT
  1406.     MOV    B,A        RESAVE
  1407.     MOV    A,C        GET C
  1408.     CMA            COMPLEMENT
  1409.     MOV    C,A        RESAVE
  1410.     INX    B        ADD 1 GIVING TWO'S COMPLEMENT
  1411. ADD    DAD    B        ADD TO NEW VALUE
  1412.     JMP    EGO        CONTINUE
  1413. * 16 BIT MULTIPLICATION
  1414. MULT    CPI    '*'        TEST FOR MULTIPLY
  1415.     JNZ    DIV        NO, TRY DIVIDE
  1416.     MOV    A,B        TEST OLD VALUE FOR ZERO
  1417.     ORA    C        AS IT IS A
  1418.     JZ    EGZ        SPECIAL CASE
  1419.     CALL    DMULT        PERFORM THE MULTIPLY
  1420.     JMP    EGO        AND CONTINUE
  1421. * MULTIPLY SUBROUTINE (ALSO USED BY RANDOM NUMBER GENERATOR)
  1422. DMULT    PUSH    D        SAVE POSITION IN SOURCE
  1423.     LXI    D,0        START OUT WITH A ZERO
  1424. MUL1    ANA    A        INSURE CARRY CLEAR
  1425.     MOV    A,B        GET B
  1426.     RAR            ROTATE
  1427.     MOV    B,A        RESAVE
  1428.     MOV    A,C        GET C
  1429.     RAR            ROTATE WITH CARRY
  1430.     MOV    C,A        REPLACE
  1431.     PUSH    PSW        SAVE FLAGS
  1432.     ORA    B        TEST FOR B-C = ZER0
  1433.     JZ    MEXIT        IF SO, WE ARE DONE
  1434.     POP    PSW        GET FLAGS BACK
  1435.     JNC    NOMAD        NO ONE BIT, DON'T ADD
  1436.     XCHG            SWAP SO WE CAN
  1437.     DAD    D        ADD TO D-E
  1438.     XCHG            AND SWAP BACK
  1439. NOMAD    DAD    H        SHIFT H-L RIGHT BY ONE BIT
  1440.     JMP    MUL1        KEEP GOING
  1441. MEXIT    DAD    D        ADD RESULT
  1442.     POP    PSW        CLEAN UP STACK
  1443.     POP    D        RESTORE SOURCE POSITION
  1444.     RET
  1445. * 16 BIT DIVISION
  1446. DIV    CPI    '%'        TEST FOR DIVIDE
  1447.     JNZ    FLOR        NO, TRY FLOR
  1448.     MOV    A,B        TEST FOR AN OLD
  1449.     ORA    C        VALUE OF ZERO,
  1450.     JZ    DIVZE        BECAUSE THAT IS  A BAD THING
  1451.     PUSH    D        SAVE SOURCE POSITION
  1452.     CALL    DODIV        PERFORM DIVIDE OPERATION
  1453.     SHLD    VARS+34        SET 'R' REMAINDER VARIABLE
  1454.     XCHG            PLACE RESULT IN H-L
  1455.     POP    D        RESTORE SOURCE POSITION
  1456.     JMP    EGO        AND CARRY ON
  1457. *
  1458. * PERFORMS 16 BIT(HL) BY 16 BIT(BC) DIVIDE, RESULT IN DE, REM IN HL
  1459. *
  1460. DODIV    MOV    A,B        GET CONTENTS OV B
  1461.     CMA            INVERT
  1462.     MOV    B,A        REPLECE
  1463.     MOV    A,C        GET CONTENTS IN C
  1464.     CMA            INVERT
  1465.     MOV    C,A        REPLACE
  1466.     INX    B        COMPLETE TWO COMPLEMENT OPERATION
  1467.     XCHG            COPY HL TO DE, LOWER HALF OF 32 BIT VALUE
  1468.     LXI    H,0        ZERO HIGHER HALF
  1469.     CALL    DIVBYT        PERFORM FIRST HALF
  1470. DIVBYT    MOV    A,D        GET UPPER HALF
  1471.     MOV    D,E        SAVE LOWER HALF
  1472.     MVI    E,8        GET LOOP COUNT
  1473. DIVTOP    DAD    H        SHIFT LEFT
  1474.     JC    OVER1        OVERFLOWED
  1475.     ADD    A        SHIFT  RESULT
  1476.     JNC    SUBB        IF NO CARRY, DON'T INC
  1477.     INX    H        ADVANCE UPPER VALUE
  1478. SUBB    PUSH    H        SAVE VALUE
  1479.     DAD    B        SUBTRACT LOWER HALF OF FRACTION
  1480.     JC    OKKK        IF WRAP PAST ZERO
  1481.     POP    H        RESTORE VALUE
  1482.     JMP    NXLP        FINISH LOOP
  1483. OKKK    INX    SP        FIX UP
  1484.     INX    SP        STACK
  1485.     INR    A        ADVANCE RESULT
  1486.     JMP    NXLP        FINISH LOOP
  1487. OVER1    ADC    A        SHIFT RESULT, +1 FOR CARRY
  1488.     JNC    OVRSUB        IF NO WRAP
  1489.     INX    H        INC. VALUE
  1490. OVRSUB    DAD    B        SUBTRACT LOWER
  1491. NXLP    DCR    E        REDUCE LOOP COUNTER
  1492.     JNZ    DIVTOP        LOOP IF NOT FINISHED
  1493.     MOV    E,A        LOWER BYTE OF RESULT
  1494.     RET
  1495. *
  1496. * HE SHOULD KNOW THAT HE CAN'T DIVIDE BY ZERO, BUT JUST IN CASE...
  1497. * WE WILL TELL HIM ANYWAY
  1498. *
  1499. DIVZE    LXI    H,DER        ADDRESS OF 'DIVIDE BYE ZERO MESSAGE'
  1500.     JMP    ERR        HANDLE LIKE ANY OTHER ERROR
  1501. * COMPARES H-L TO B-C, Z=1 IF HL=BC, C=1 IF HL<BC
  1502. COMP    MOV    A,H        GET HIGH BYTE OF HL
  1503.     CMP    B        COMPARE WITH HIGH BYTE OF BC
  1504.     RNZ            IF NOT SAME, LOWER BYTE CAN BE IGNORED
  1505.     MOV    A,L        GET LOW BYTE OF HL
  1506.     CMP    C        COMPARE WITH LOW BYTE OF BC
  1507.     RET
  1508. * FLOOR, RETURNS THE LESSER OF THE TWO NUMBERS
  1509. FLOR    CPI    '\'        IS IT FLOOR?
  1510.     JNZ    CEIL        NO, TRY CEILING
  1511.     CALL    COMP        COMPARE NEW TO OLD
  1512.     JC    EGO        IF LESS, WE ARE OK (RESULT IS ALREADY IN HL)
  1513. SWAP    MOV    H,B        MAKE OLD NUMBER..
  1514.     MOV    L,C        INTO THE NEW NUMBER..
  1515.     JMP    EGO        CONTINUE
  1516. * CEILING, RETURNS THE GREATER OF THE TWO NUMBERS
  1517. CEIL    CPI    '/'        IS IT CEILING?
  1518.     JNZ    LAND        NO, TRY LOGICAL AND
  1519.     CALL    COMP        COMPARE NEW AND OLD
  1520.     JNC    EGO        IF GREATER, WE ARE OK (RESULT ALREADY IN HL)
  1521.     JMP    SWAP        MAKE OLD NEW AND CONTINUE
  1522. * LOGICAL AND
  1523. LAND    CPI    '&'        IF IT LOGICAL AND ?
  1524.     JNZ    LOR        NO, TRY LOGICAL OR
  1525.     MOV    A,B        GET HIGH BYTE OF OLD
  1526.     ANA    H        AND WITH HIGH BYTE OF NEW
  1527.     MOV    H,A        AND REPLACE HIGH BYTE OF NEW
  1528.     MOV    A,L        GET LOW BYTE OF OLD
  1529.     ANA    C        AND WITH LOW BYTE OF NEW
  1530.     JMP    CPYL        CONTINUE
  1531. * LOGICAL OR
  1532. LOR    CPI    '|'        TEST FOR LOGICAL OR
  1533.     JNZ    GRTR        NO, TRY GREATER THAN
  1534.     MOV    A,H        GET HIGH BYTE OF NEW
  1535.     ORA    B        OR WITH HIGH BYTE OF OLD
  1536.     MOV    H,A        AND REPLACE HIGH BYTE OF NEW
  1537.     MOV    A,L        GET LOW BYTE OF NEW
  1538.     ORA    C        OR WITH LOW BYTE OF OLD
  1539. CPYL    MOV    L,A        AND REPLACE LOW BYTE OF NEW
  1540.     JMP    EGO        CONTINUE
  1541. * GREATER THAN, RETURNS ONE OR ZERO
  1542. GRTR    CPI    '>'        TEST FOR GREATER THAN
  1543.     JNZ    LETH        IF NOT, TRY LESS THAN
  1544.     CALL    COMP        COMPARE OLD AND NEW
  1545.     JZ    EGZ        FALSE IF EQUAL
  1546.     JC    EGZ        FALSE IF LESS THAN
  1547.     JMP    EG1        TRUE IF NOT LESS OR EQUAL
  1548. * LESS THAN, RETURNS ONE OR ZERO
  1549. LETH    CPI    '<'        IS IT LESS THAN?
  1550.     JNZ    ENOP        NO, TRY NO-OP OPERATOR
  1551.     CALL    COMP        COMPARE OLD AND NEW
  1552.     JC    EG1        TRUE IF LESS
  1553.     JMP    EGZ        FALSE IF NOT LESS
  1554. * NO-OP OPERATOR, RETURNS NEW VALUE ONLY
  1555. ENOP    CPI    ';'        IS IT NO-OP?
  1556.     JZ    EGO        IF SO, DON'T DO ANYTHING
  1557. * ASSIGNMENT, SET A VARIABLE'S VALUE
  1558. ASST    CPI    '='        TEST FOR ASSIGNMENT
  1559.     JNZ    EQUAL        IF NOT, TRY EQUALITY
  1560.     STA    EFLAG        SET ASSIGNMENT FLAG
  1561.     INX    D        BACK UP TO VARIABLE NAME
  1562.     LDAX    D        GET VARIABLE CHARACTER
  1563.     CPI    ']'        TEST FOR ARRAY STORAGE
  1564.     JZ    ASTOR        IF SO, STORE INTO ARRAY
  1565.     MOV    H,B        GET OLD VALUE
  1566.     MOV    L,C        INTO H-L (WHERE STORE WANTS THEM)
  1567.     CPI    '?'        TEST FOR SETTING RANDOM SEED
  1568.     JZ    SRSEED        IF SO, SET THE SEED
  1569.     CALL    STOR        STORE VALUE INTO VARIABLE
  1570. STRT    DCX    D        STEP BACK FROM VARIABLE
  1571.     JMP    EGO        AND CONTINUE
  1572. * SET THE RANDOM SEED
  1573. SRSEED    SHLD    SEED        SO WE CAN STORE IN SEED
  1574.     JMP    STRT        AND CONTINUE
  1575. * SET THE VALUE OF AN ARRAY ELEMENT
  1576. ASTOR    PUSH    H        SAVE H-L
  1577.     CALL    DOEXP        CALCULATE INDEX VALUE
  1578.     DCX    D        BACK UP PAST '['
  1579.     LDAX    D        GET ARRAY NAME
  1580.     CALL    LOOKT        LOOK UP IT'S ADDRESS IN THE TABLE
  1581.     MOV    B,H        GET ARRAY ADDRESS
  1582.     MOV    C,L        INTO B-C
  1583.     POP    H        RERSTORE H-L
  1584.     LDAX    D        GET ARRAY NAME BACK
  1585.     CPI    '@'        TEST FOR 'MAGIC', MEMORY REFERENCE
  1586.     JZ    STMEM        IF SO, SET MEMORY LOCATION
  1587.     MOV    A,H        GET HIGH BYTE OF VALUE
  1588.     STAX    B        STASH IN ARRAY
  1589.     INX    B        POINT TO NEXT
  1590. STMEM    MOV    A,L        GET LOW BYTE OF VALUE
  1591.     STAX    B        STASH IN ARRAY
  1592.     JMP    STRT        CONTINUE
  1593. * TEST FOR EQUALITY.  ('==')
  1594. EQUAL    SUI    $81        IS A '=='?
  1595.     JNZ    GEQL        IF NOT, TRY GREATER OR EQUAL
  1596.     CALL    COMP        COMPARE OLD AND NEW
  1597.     JZ    EG1        TRUE IF EQUAL
  1598.     JMP    EGZ        FALSE IF NOT EQUAL
  1599. * GREATER OR EQUAL.  ('>=')
  1600. GEQL    DCR    A        TEST FOR '>='?
  1601.     JNZ    LEQL        NO, TRY LESS OR EQUAL
  1602.     CALL    COMP        COMPARE OLD AND NEW
  1603.     JC    EGZ        FALSE IF LESS THAN
  1604.     JMP    EG1        TRUE IF GREATER OR EQUAL
  1605. * LESS OR EQUAL.  ('<=')
  1606. LEQL    DCR    A        TEST FOR '<='?
  1607.     JNZ    NEQL        IF NOT, TRY NOT EQUAL
  1608.     CALL    COMP        COMPARE OLD AND NEW
  1609.     JZ    EG1        TRUE IF SAME
  1610.     JC    EG1        TRUE IF LESS THAN
  1611.     JMP    EGZ        FALSE OTHERWISE
  1612. * TEST FOR NOT EQUAL.  ('-=')
  1613. NEQL    DCR    A        IS IT '-='?
  1614.     JNZ    SYNT        BEATS ME WHAT IT IS!
  1615.     CALL    COMP        COMPARE OLD AND NEW
  1616.     JZ    EGZ        IF SAME, FALSE
  1617. * RETURN RESULT OF ONE
  1618. EG1    LXI    H,1        SET RESULT TO ONE
  1619.     JMP    EGO        PASS ON RESULT
  1620. * RETURN RESULT OF ZERO
  1621. EGZ    LXI    H,0        SET RESULT TO ZERO
  1622. * END OF OPERATION, GET NEXT OPERATOR
  1623. EGO    CALL    FE        GET NEXT CHARACTER
  1624.     RZ            IF WE PASS BEGINNING OF EXPRESSION, QUIT
  1625.     CPI    '('        ARE WE RETURNING FROM A NEST?
  1626.     RZ            IF SO, BACK UP ONE LEVEL
  1627.     CPI    '['        FINISHED AN ARRAY INDEX EVALUATION?
  1628.     RZ            RETURN TO MAIN EXPRESSION
  1629.     CPI    '='        IF IT A MULTI-CHARACTER OPERATOR
  1630.     JNZ    EGO1        IF NOT, DON'T PRE-EVALUATE
  1631.     DCX    D        BACK UP TO PRECEDING CHARACTER
  1632.     LDAX    D        GET PRECEDING CHARACTER
  1633.     CPI    '='        IS IT '=='?
  1634.     MVI    B,$81        SET UNIQUE CODE
  1635.     JZ    EGO2        IF '==' THEN WE HAVE IT
  1636.     INR    B        NEXT UNIQUE CODE
  1637.     CPI    '>'        IS IT '>='?
  1638.     JZ    EGO2        IF SO, WE HAVE IT
  1639.     INR    B        NEXT UNIQUE CODE
  1640.     CPI    '<'        IS IT '<='?
  1641.     JZ    EGO2        IF SO, WE HAVE IT
  1642.     INR    B        NEXT UNIQUE CODE
  1643.     CPI    '-'        IS IT '-='?
  1644.     JZ    EGO2        IF SO, WE HAVE IT
  1645.     INX    D        WASN'T A TWO CHARACTER OPERATOR. BACK UP
  1646.     MVI    A,'='        MUST HAVE BEEN A SIMPLE '='
  1647.     JMP    EGO1        CONTINUE EVALUATING EXPRESSION
  1648. EGO2    MOV    A,B        SET OPERATOR TO OUR UNIQUE CODE
  1649.     JMP    EGO1        AND CONTINUE EVALUATING EXPRESSION
  1650. * FINDS NEXT CHARACTER IN EXPRESSION, SETS Z FLAG IF WE PASS THE BEGINNING
  1651. FE    LDA    P        GET ADDRESS OF BEGINNING OF LINE
  1652.     CMP    E        ARE WE THERE??
  1653.     RZ            IF SO, WE ARE FINISHED
  1654.     LDAX    D        GET CHARACTER FROM SOURCE
  1655.     CPI    ' '        IS A (USELESS) BLANK?
  1656.     RNZ            IF NOT, WE ARE FINISHED
  1657.     DCX    D        BACK UP ANOTHER CHARACTER
  1658.     JMP    FE        AND TRY AGAIN
  1659. * CALCULATE A PSEUDO-RANDOM VALUE
  1660. RANDR    LHLD    SEED        GET RANDOM SEED
  1661.     MOV    A,H        GET HIGH BYTE OF SEED
  1662.     ANI    $F7        AND WITH HIGH MASK
  1663.     PUSH    PSW        SAVE PARITY FLAG
  1664.     MOV    A,L        GET LOW BYTE OF SEED
  1665.     ANI    $42        AND WITH LOW BYTE OF MASK
  1666.     PUSH    PSW        SAVE PARITY FLAG
  1667.     POP    B        GET FLAGS IN C
  1668.     MOV    A,C        COPY TO A
  1669.     POP    B        GET FIRST SET OF FLAGS IN C
  1670.     XRA    C        COMPUTE PARITY FOR ENTIRE WORD
  1671.     RRC            MOVE COMPUTED
  1672.     RRC            PARITY INTO
  1673.     RRC            THE CARRY FLAG
  1674.     CMC            COMP, SO SHIFT IN 1 IF EVEN
  1675.     MOV    A,L        GET LOW BYTE OF SEED
  1676.     RAL            SHIFT IN CARRY, OUT HIGH BIT
  1677.     MOV    L,A        RESAVE
  1678.     MOV    A,H        GET HIGH BYTE OF SEED
  1679.     RAL            SHIFT IN CARRY (HIGH BIT OF OLD LOWER)
  1680.     MOV    H,A        RESAVE
  1681.     SHLD    SEED        RESULT IS NEW SEED
  1682.     JMP    DCLB        KEEP GOING
  1683. *
  1684. * EVALUATES A CHARACTER EXPRESSION
  1685. *
  1686. CEXP    CALL    CLBF        CLEAR EXTRA BUFFER
  1687.     INX    D        SKIP TO END OF EXPRESSION
  1688.     MVI    A,'+'        TO BEGIN, CONCATINATE A NULL STRING
  1689. CG1    PUSH    PSW        STACK THE OPERATOR FOR LATER
  1690.     CALL    PUSHB        COPY NEW BUFFER INTO OLD BUFFER
  1691.     CALL    CLBF        CLEAR THE NEW BUFFER
  1692.     DCX    D        BACK UP IN SOURCE
  1693.     CALL    FE        GET CHARACTER AND TEST FOR END
  1694.     CPI    $22        TEST FOR QUOTE
  1695.     JZ    CQ        IF SO, HANDLE QUOTED STRING
  1696.     CPI    '$'        TEST FOR CHARACTER VARIABLE
  1697.     JNZ    SYNT        IF NOT, IT'S NOT ANYTHING I RECOGNISE
  1698. CV    DCX    D        BACK UP PAST DOLLAR SIGN
  1699.     LDAX    D        GET VARIABLE NAME
  1700.     CPI    ']'        TEST FOR INDEX INTO CHARACTER VARIABLE
  1701.     JZ    CINDX        GET INDEX VALUE
  1702.     CALL    LTA        GET ADDRESS OF VARIABLE
  1703.     PUSH    D        SAVE SOURCE POSITION
  1704.     XCHG            SWAP ADDRESS TO D-E
  1705.     DCX    D        BACK UP IN SOURCE
  1706.     JMP    Q0        SAVE VARIABLE IN NEW BUFFER
  1707. * BACKUP TO PRECEDING QUOTE
  1708. CQ    DCX    D        BACKUP IN SOURCE
  1709.     LDAX    D        GET CHARACTER FROM SOURCE
  1710.     CPI    $0D        TEST FOR END OF LINE
  1711.     JZ    SYNT        IF SO, THERE IS NO CLOSEING QUOTE
  1712.     CPI    $22        TEST FOR CLOSEING QUOTE
  1713.     JNZ    CQ        IF NO, KEEP LOOKING
  1714.     PUSH    D        SAVE ENDING POSITION
  1715. Q0    LXI    H,XBF        GET ADDRESS OF NEW (EXTRA) BUFFER
  1716. Q1    INX    D        ADVANCE TO SOURCE OR VARIABLE CHARACTER
  1717.     LDAX    D        GET CHARACTER
  1718.     CPI    $22        TEST FOR CLOSEING QUOTE
  1719.     JZ    Q2        IF SO, STOP COPYING
  1720.     CPI    $FF        TEST FOR END OF VARIABLE
  1721.     JZ    Q2        IF SO, STOP COPYING
  1722.     MOV    M,A        SAVE IN BUFFER
  1723.     INX    H        ADVANCE IN BUFFER
  1724.     JMP    Q1        KEEP COPYING
  1725. Q2    POP    D        GET POSITION BACK
  1726. Q3    DCX    D        BACK UP TO OPERATOR
  1727.     POP    PSW        GET OPERATOR
  1728.     CPI    '+'        TEST FOR CONCATIONATION
  1729.     JNZ    Q5        NO, TRY ASSIGNMENT
  1730. * CONCATONATION. XBF=XBF+TB
  1731. QPP    LXI    B,TB        ADDRESS OF TEMPORARY BUFFER
  1732. Q4    LDAX    B        GET CHARACTER FROM BUFFER
  1733.     MOV    M,A        MOVE TO BUFFER
  1734.     INX    B        ADVANCE IN OLD
  1735.     INX    H        ADVANCE IN NEW
  1736.     MOV    A,C        GET ADDRESS IN OLD
  1737.     CPI    TB+35        TEST FOR OVER
  1738.     JC    Q4        IF SO, STOP
  1739.     LHLD    XBF        GET CHARACTER FROM BUFFER
  1740.     MVI    H,0        SET HIGH BYTE TO ZERO
  1741.     JMP    Q9        CONTINUE
  1742. * ASSIGNMENT
  1743. Q5    CPI    '='        TEST FOR ASSIGNMENT
  1744.     JNZ    Q6        IF NOT, TRY EQUALITY
  1745.     INX    D        SKIP TO VARIABLE NAME
  1746.     INX    D        SKIP TO DOLLARSIGN
  1747.     LDAX    D        GET DOLLARSIGN
  1748.     DCX    D        BACK UP TO VARIABLE NAME
  1749.     CPI    '$'        TEST FOR DOLLAR SIGN
  1750.     JNZ    SYNT        IF NOT, THIS AIN'T NO CHARACTER VARIABLE
  1751.     STA    EFLAG        SET ASSIGNMENT FLAG
  1752.     LDAX    D        GET VARIABLE NAME
  1753.     DCX    D        BACK UP BAST NAME
  1754.     CALL    LTA        GET IT'S ADDRESS
  1755.     JMP    QPP        COPY IT OVER
  1756. * TEST FOR EQUALITY
  1757. Q6    CPI    $81        TEST FOR '=='
  1758.     JNZ    X0        NO, TRY '=-'
  1759.     CALL    COMSTR        COMPARE STRINGS
  1760.     JMP    Q9        CONTINUE
  1761. * COMPARES STRINGS. SETS H-L TO 1 OR 0 IF EQUAL OR NOT EQUAL
  1762. COMSTR    LXI    B,TB        GET ADDRESS OF OLD STRING
  1763.     LXI    H,XBF        ADDRESS OF NEW STRING
  1764. Q7    LDAX    B        GET CHARACTER FROM OLD
  1765.     CMP    M        TEST AGAINST NEW
  1766.     JNZ    Q8        IF NOT, THEY ARE UNEQUAL
  1767.     INX    B        NEXT PLACE IN OLD
  1768.     INX    H        NEXT PLACE IN NEW
  1769.     INR    A        TEST FOR END OF STRING
  1770.     JNZ    Q7        IF NOT, CONTINUE TESTING
  1771.     LXI    H,1        INDICATE THEY ARE EQUAL
  1772.     RET
  1773. Q8    LXI    H,0        INDICATE NOT EQUAL
  1774.     RET
  1775. * NOT EQUAL .. '-='
  1776. X0    CPI    $82        TEST FOR '-='
  1777.     JNZ    SYNT        BEATS ME, BUT IT ISN'T RIGHT
  1778.     CALL    COMSTR        TEST STRINGS
  1779.     MOV    A,L        GET RESULT
  1780.     XRI    1        AND COMPLEMENT IT
  1781.     MOV    L,A        REPLACE IN RESULT
  1782. * GET NEXT STRING
  1783. Q9    CALL    FE        GET NEXT CHARACTER
  1784.     STC            INDICATE CHARACTER EXPRESSION
  1785.     RZ            IF END OF LINE, QUIT
  1786.     CPI    '('        TEST FOR END OF NUMERIC SUBSTRING
  1787.     RZ            QUIT, INDICATING NUMBERIC RESULT
  1788.     CPI    '='        TEST FOR EQUAL,ASSIGNMENT, OR NOT EQUALS
  1789.     JNZ    CG1        NO, NO NEED TO TEST FURTHER
  1790. QTST    DCX    D        BACK UP TO PREVIOUS CHARACTER
  1791.     LDAX    D        GET CHARACTER
  1792.     MOV    B,A        SAVE FOR COMPARISON
  1793.     CPI    '='        TEST FOR '=='
  1794.     MVI    A,$81        INDICATE '=='
  1795.     JZ    CG1        CONTINUE
  1796.     MOV    A,B        GET CHARACTER BACK
  1797.     CPI    '-'        TEST FOR '-='
  1798.     MVI    A,$82        INDICATE '-='
  1799.     JZ    CG1        CONTINUE
  1800.     INX    D        ADVANCE BACK TO PREVIOUS CHARACTER
  1801.     MVI    A,'='        INDICATE '='
  1802.     JMP    CG1        CONTINUE
  1803. * CLEARS THE TEXT BUFFER
  1804. CLBF    LXI    H,XBF        GET ADDRESS OF BUFFER
  1805.     MVI    A,40        CLEAR FOR LENGTH OF 40
  1806. CL2    MVI    M,$FF        CLEAR TO NULL CHARACTER
  1807.     INX    H        NEXT POSITION IN BUFFER
  1808.     DCR    A        REDUCE COUNT OF REMAINING
  1809.     JNZ    CL2        KEEP GOING TILL WE ARE FINISHED
  1810.     RET
  1811. * COPY'S NEW BUFFER INTO OLD BUFFER
  1812. PUSHB    PUSH    D        SAVE POSITION IS SOURCE
  1813.     LXI    D,XBF        GET ADDRESS OF NEW BUFFER
  1814.     LXI    H,TB        GET ADDRESS OF OLD BUFFER
  1815.     MVI    B,40        COPY 40 CHARACTERS
  1816. PU1    LDAX    D        GET CHARACTER FROM NEW
  1817.     MOV    M,A        SAVE IN OLD
  1818.     INX    H        NEXT POSITION IN OLD
  1819.     INX    D        NEXT POSITION IN NEW
  1820.     DCR    B        REDUCE COUNT
  1821.     JNZ    PU1        KEEP GOING TILL 40 ARE MOVED
  1822.     POP    D        RESTORE POSITION IN SOURCE
  1823.     RET
  1824. * INDEXED CHARACTER VARIABLE, EXTRACT A SINGLE CHARACTER
  1825. CINDX    CALL    DOEXP        EVALUATE INDEX EXPRESSION
  1826.     MOV    A,L        GET INDEX VALUE
  1827.     PUSH    PSW        SAVE INDEX VALUE
  1828.     DCX    D        BACK UP TO VARIABLE NAME
  1829.     LDAX    D        GET VARIABLE NAME
  1830.     CPI    '@'        TEST FOR 'MAGIC' CHR$ VARIABLE
  1831.     JZ    CHR        IF SO, HANDLE SPECIAL CASE
  1832.     CALL    LTA        GET TEXT VARIABLE ADDRESS
  1833.     POP    PSW        GET INDEX BACK
  1834.     CPI    35        TEST FOR TOO BIG
  1835.     JNC    DIMERR        IF SO, TELL HIM HE SCREWED UP
  1836.     MOV    C,A        GET INTO A DOUBLE PAIR
  1837.     DAD    B        SO WE CAN DAD IT TO THE ADDRESS
  1838.     MOV    A,M        AND GET THE CHARACTER
  1839. FILBUF    LXI    H,XBF        ADDRESS OF TEXT BUFFER
  1840.     MOV    M,A        PLACE CHARACTER THERE
  1841.     INX    H        BUMP TO NEXT POSITION
  1842.     JMP    Q3        AND FILL WITH NULLS
  1843. *
  1844. * 'MAGIC' CHARACTER ARRAY, RETURNS CHARACTER WITH VALUE OF IT'S INDEX
  1845. *
  1846. CHR    POP    PSW        GET INDEX VALUE
  1847.     JMP    FILBUF        SAVE IN BUFFER AND PAD WITH NULLS
  1848. * END OF BASIC INTERPRETER CODE SECTION
  1849.     PAGE
  1850. *
  1851. **********************************************************************
  1852. *                          COMMAND TABLE
  1853. *
  1854. *   FORMAT IS:
  1855. *               COMMAND WORDS, HIGH BIT SET ON LAST CHARACTER
  1856. *               ADDRESS OF COMMAND PROCESSOR FOLLOWES
  1857. *               ENTRY OF HEX 00 INDICATES LAST ENTRY IN TABLE (DEFAULT)
  1858. *
  1859. **********************************************************************
  1860. *
  1861. * COMMANDS ALLOWED ONLY FROM WITHING A PROGRAM..
  1862. PTAB    STR    'NEX'
  1863.     DB    'T'+$80
  1864.     DW    NEXT
  1865.     STR    'THE'
  1866.     DB    'N'+$80
  1867.     DW    THEN
  1868.     STR    'GOSU'
  1869.     DB    'B'+$80
  1870.     DW    GOSUB
  1871.     STR    'RETUR'
  1872.     DB    'N'+$80
  1873.     DW    RETURN
  1874.     STR    'FO'
  1875.     DB    'R'+$80
  1876.     DW    FOR
  1877.     STR    'I'
  1878.     DB    'F'+$80
  1879.     DW    IF
  1880. DATCMD    STR    'DAT'
  1881.     DB    'A'+$80
  1882.     DW    RNEXT
  1883.     STR    'LI'
  1884.     DB    'F'+$80
  1885.     DW    LIF
  1886. * COMMANDS ALLOWED FROM BOTH A PROGRAM, AND INTERACTIVE KEYBOARD ENTRY
  1887. KTAB    STR    'GOT'
  1888.     DB    'O'+$80
  1889.     DW    GOTO
  1890.     STR    'LE'
  1891.     DB    'T'+$80
  1892.     DW    LET
  1893.     STR    'PRIN'
  1894.     DB    'T'+$80
  1895.     DW    PRINT
  1896.     STR    'US'
  1897.     DB    'R'+$80
  1898.     DW    USR
  1899.     STR    'REA'
  1900.     DB    'D'+$80
  1901.     DW    READ
  1902.     STR    'PLO'
  1903.     DB    'T'+$80
  1904.     DW    PLOT
  1905.     STR    'RE'
  1906.     DB    'M'+$80
  1907.     DW    REM
  1908.     STR    'DI'
  1909.     DB    'M'+$80
  1910.     DW    DIM
  1911.     STR    'RU'
  1912.     DB    'N'+$80
  1913.     DW    RUN
  1914.     STR    'ORDE'
  1915.     DB    'R'+$80
  1916.     DW    ORDER
  1917.     STR    'INPU'
  1918.     DB    'T'+$80
  1919.     DW    INPUT
  1920.     STR    'CLEA'
  1921.     DB    'R'+$80
  1922.     DW    CLEAR
  1923.     STR    'STO'
  1924.     DB    'P'+$80
  1925.     DW    STOP
  1926.     STR    'EN'
  1927.     DB    'D'+$80
  1928.     DW    INIT
  1929.     STR    'LIS'
  1930.     DB    'T'+$80
  1931.     DW    LIST
  1932.     STR    'NE'
  1933.     DB    'W'+$80
  1934.     DW    NEW
  1935.     STR    'SIZ'
  1936.     DB    'E'+$80
  1937.     DW    SIZE
  1938.     STR    'LOA'
  1939.     DB    'D'+$80
  1940.     DW    LOAD
  1941.     STR    'SAV'
  1942.     DB    'E'+$80
  1943.     DW    SAVE
  1944.     STR    'EXI'
  1945.     DB    'T'+$80
  1946.     DW    EXIT
  1947.     DB    0        UNRECOGNIZED COMMAND, ASSUME 'LET'
  1948.     DW    LET
  1949. *
  1950. ***************************************************************
  1951. *                    STRINGS AND MESSAGES
  1952. ***************************************************************
  1953. *
  1954. * ERROR MESSAGES..
  1955. *
  1956. DER    STRZ    'DIVIDE BY ZERO'   DIVIDE BY ZERO
  1957. IERMS    STR    'BAD DATA - RETRY' BAD RESPONSE TO INPUT STATEMENT
  1958.     DB    $0D
  1959. CSTK    STRZ    'NESTING'    INVALID FOR/NEXT, GOSUB/RETURN NESTING
  1960. LIN    STRZ    'LINE NUMBER'    GOTO, GOSUB, OR ORDER TO UNKNOWN LINE
  1961. NP    STRZ    'NO PROGRAM'    RUN OR SAVE EMPTY PROGRAM
  1962. INL    STRZ    ' IN LINE '    INDICATES LINE ERROR WAS IN
  1963. SYN    STRZ    'SYNTAX'    DOES NOT FOLLOW SYNTAX RULES
  1964. DTXT    STRZ    'DATA'        BAD LINE OR DATA TYPE
  1965. OVM    STRZ    'DIMENSION'    TO MANY ARRAYS, ARGUMENT OUT OF RANGE
  1966. *
  1967. * INFORMATIONAL MESSAGES..
  1968. *
  1969. RDY    STR    'READY'        READY PROMPT
  1970.     DB    $0D
  1971. STMSG    STRZ    'STOP'        INDICATES PROGRAM STOPPED
  1972. EM    STRZ    ' ERROR'    INDICATES ERROR OCCURED
  1973. SIMSG    STR    ' BYTES'    DISPLAYED IN RESPONSE TO 'SIZE'
  1974.     DB    $0D
  1975. ENDIT    EQU    *
  1976.